2017-07-24 104 views
4

我試圖專注Expr曖昧類模板實例包

#include <tuple> 
#include <type_traits> 
#include <iostream> 

template<class Tp, class List> 
struct Expr { 
    Expr(){std::cout << "0"<< std::endl;}; 
}; 

//specialization #1 
template<class Tp, int...i> 
struct Expr<Tp,std::tuple<std::integral_constant<int,i>...>> { 

    Expr(){std::cout << "1"<< std::endl;}; 
}; 

//specialization #2 
template<int...i> 
struct Expr<double,std::tuple<std::integral_constant<int,i>...>> { 

    Expr(){std::cout << "2"<< std::endl;}; 
}; 

int main() { 

    typedef std::tuple<std::integral_constant<int,1>> mylist; 

    Expr<double,mylist> test{}; 

    return 0; 
} 

但是,我得到了以下編譯器錯誤:

[x86-64 gcc 6.3] error: ambiguous template instantiation for 'struct Expr<double, std::tuple<std::integral_constant<int, 1> > >' 
[x86-64 gcc 6.3] error: variable 'Expr<double, std::tuple<std::integral_constant<int, 1> > > test' has initializer but incomplete type 

這裏,尤其是第一個錯誤困擾我。我試圖弄清楚爲什麼這是一個模棱兩可的實例。

編譯器應該選擇specialization #2嗎?

如果我避免將非類型參數包int...i包裝在std::integral_constant中,它會毫無問題地進行編譯,並選擇第二種特殊化。下面的示例工程:

#include <tuple> 
#include <type_traits> 
#include <iostream> 

template<class Tp, class List> 
struct Expr { 
    Expr(){std::cout << "0"<< std::endl;}; 
}; 

//specialization #1 
template<class Tp, class...args> 
struct Expr<Tp,std::tuple<args...>> { 

    Expr(){std::cout << "1"<< std::endl;}; 
}; 

//specialization #2 
template<class...args> 
struct Expr<double,std::tuple<args...>> { 

    Expr(){std::cout << "2"<< std::endl;}; 
}; 

int main() { 

    typedef std::tuple<std::integral_constant<int,1>> mylist; 

    Expr<double,mylist> test{}; 

    return 0; 
} 

回答

1

這是不對的。這是一個海灣合作委員會的錯誤(我找不到一個錯誤報告,也許還沒有報道過?)。

你是對的,專業化#2必須選擇。因爲有2個匹配的專業化,部分排序選擇最專業的一個,在你的情況是#2(double作爲第一個參數比任何類型作爲第一個參數更專業)。

此外,鏗鏘編譯您的代碼without any problems