问题来自here - 我想创建一种解决更普遍问题的方法。考虑一个例子:
#include <utility>
template<class T, std::size_t>
using deduced = T;
template<std::size_t N, class = std::make_index_sequence<N>>
struct Foo;
template<std::size_t N, std::size_t... Is>
struct Foo<N, std::index_sequence<Is...>>{
template <class... Args>
void Bar(deduced<Args, Is>...)
{ }
};
int main() {
Foo<3> myfoo;
myfoo.Bar(true, 2.0f, 3); // OK
//myfoo.Bar(1, 2, 3, 4); // error
}
clang编译代码没有问题,另一方面gcc显示以下错误:
prog.cc: In function 'int main()':
prog.cc:18:27: error: no matching function for call to 'Foo<3ul>::Bar(bool, float, int)'
myfoo.Bar(true, 2.0f, 3); // valid
^
prog.cc:12:10: note: candidate: template<class ... Args> void Foo<N, std::integer_sequence<long unsigned int, Is ...> >::Bar(deduced<Args, Is>...) [with Args = {Args ...}; long unsigned int N = 3ul; long unsigned int ...Is = {0ul, 1ul, 2ul}]
void Bar(deduced<Args, Is>...)
^~~
prog.cc:12:10: note: template argument deduction/substitution failed:
prog.cc:18: confused by earlier errors, bailing out
令我感到困惑的是,当使用相同的别名时,gcc没有扣除问题,但不涉及外部参数包,例如:
void Bar(deduced<Args, 0>...)
所以问题是 - 将外部和内部类的参数包与此表单的别名组合以使编译器推导出其中一个模板参数或者是gcc bug是否合法?
编辑(根据bogdan的评论):
代码也给MSVC(2017 RC)带来了麻烦,但是这种形式与EDG编译器一起工作,icc(版本16和17)似乎也能很好地处理代码。值得注意的是,使用类而不是别名的类似代码(在某些地方也被视为推导上下文example by bogdan)会给编译器带来更多麻烦 - 只有clang似乎能很好地处理这个版本(?)