2017-07-24 105 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