C++ 模板演绎,是否符合要求?

C++ 模板演绎,是否符合要求?,c++,c++11,templates,variadic-templates,C++,C++11,Templates,Variadic Templates,这段代码似乎不正确,因为我得到了编译器错误。我试图理解为什么: template <class ... Ts> struct type_list{}; template <class ... Ts, class T_, class ... Ts_> auto foo(type_list<Ts...>, Ts&&..., T_&&t, Ts_&&...) { return sizeof(T_); } i

这段代码似乎不正确,因为我得到了编译器错误。我试图理解为什么:

template <class ... Ts>
struct type_list{};

template <class ... Ts, class T_, class ... Ts_>
auto foo(type_list<Ts...>, Ts&&..., T_&&t, Ts_&&...) {
    return sizeof(T_);
}

int main() {
  std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
  return 0;
}
模板
结构类型_列表{};
模板
自动foo(类型列表,Ts&&…,T&&&T,Ts&&&…){
返回大小of(T_);
}
int main(){

std::cerrClang从两个相互冲突的来源推断出
Ts
type\u list
Ts&&…
。因为您使用
type\u list{}
调用
foo
Ts
首先被推断为
{int}
。但是,由于最后一个参数
Ts&&…
具有参数包的类型,因此它可以捕获所有参数;在这种情况下,最后两个参数(而
T&&T
被传递
5
),这将
Ts&
推断为
{double,int}
(和
T
作为
int
).这使得
Ts
没有参数,因此推断为
{}

因此,Clang的错误消息:
Ts
被推断为
{}
{int}
(错误消息中的
(vs.)

请注意,GCC的做法有所不同:

错误:函数“auto-foo(type_-list,Ts&&…,T_&&&,Ts_&&…[带Ts={int};T_==int;Ts_={double,int}”)的参数太少

它试图将
Ts
推断为
{int}
,但仍然将
Ts
推断为
{double,int}
,因此无法给出正确的参数数

进一步解释,考虑以下内容:

template <class ... Ts>
struct type_list{};

template <class ... Ts>
auto foo(type_list<Ts...>, Ts...) {
    return sizeof...(Ts);
}

int main() {
  std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
}
模板
结构类型_列表{};
模板
自动foo(类型列表,Ts…){
返回…的大小(Ts);
}
int main(){

C++没有尝试所有的可能性并找到唯一合法的。它遵循非常具体的规则,如果这些规则不起作用,它会生成一个错误

一般来说,如果推断出一个
包,则该包必须是最后一个包。尝试绕过它将失败

以下是一个可以避免您的问题的解决方案:

template <class ... Ts, class...Us>
auto foo(type_list<Ts...>, Us&&...us) {
    return [](Ts&&...ts, auto&& t, auto&&...) {
        return sizeof(t);
    }(std::forward<Us>(us)...);
}

int main() {
  std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
  return 0;
}
模板
自动foo(类型列表,美国和…美国){
返回[](Ts&&…Ts,auto&&t,auto&&…){
返回大小f(t);
}(标准:远期(美国)…);
}
int main(){

std::cerr编译器应该如何决定推断哪个
Ts
?@Fureeish@NirFriedman您有什么理由想直接使用
type\u list
函数参数而不是模板参数吗?非常感谢您提供的替代解决方案!
template <class ... Ts>
struct type_list{};

template <class... Ts, class... Ts_>
auto foo(type_list<Ts...>, Ts_..., Ts...) {
    return sizeof...(Ts);
}

int main() {
  std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
}
template <class ... Ts, class...Us>
auto foo(type_list<Ts...>, Us&&...us) {
    return [](Ts&&...ts, auto&& t, auto&&...) {
        return sizeof(t);
    }(std::forward<Us>(us)...);
}

int main() {
  std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
  return 0;
}