简体   繁体   English

具有非类型参数包的模糊类模板实例化

[英]Ambiguous class template instantiation with nontype parameter packs

I was trying to specialize Expr : 我正在尝试专门研究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;
}

However, I got the following compiler errors: 但是,出现以下编译器错误:

[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

Here, especially the first error bothers me. 在这里,尤其是第一个错误困扰着我。 I have tried to figure out why this is an ambiguous instantiation. 我试图弄清楚为什么这是一个模棱两可的实例。

Shouldn't specialization #2 be chosen by the compiler? 编译器不应该选择specialization #2吗?

If I avoid wrapping the non-type parameter pack int...i in std::integral_constant it compiles without any problem and the second specialization is chosen. 如果我避免将非类型参数包int...i包装在std::integral_constant则可以毫无问题地进行编译,并选择第二种特殊化方法。 The following example works: 以下示例起作用:

#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;
}

That can't be right. 那是不对的。 This is a gcc bug (I can't find a bug report to it, maybe it hasn't been reported yet?). 这是一个gcc错误(我找不到错误报告,也许还没有报告?)。

You are right, specialization #2 has to be chosen. 没错,必须选择专业化#2。 Because there are 2 specializations that match, partial ordering selects the most specialized one, which in your case is #2 ( double as first parameter is more specialized than any type as first parameter). 因为有两个匹配的特殊化,所以偏序选择最特殊的一个,在您的情况下为#2(作为第一个参数的double精度比任何类型的第一个参数更特殊)。

Additionally, clang compiles your code without any problems . 此外,clang可以毫无问题地编译您的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM