下面的c++ 20程序:
#include <utility>
#include <cstddef>
template<typename... Args>
class C {
template<size_t... I>
static void call(
std::index_sequence<I...> = std::index_sequence_for<Args...>{}
) {}
};
int main() {
C<long int>::call();
}
编译失败,错误信息:
test.cc: In static member function ‘static void C<Args>::call(std::index_sequence<I ...>) [with long unsigned int ...I = {}; Args = {long int}; std::index_sequence<I ...> = std::integer_sequence<long unsigned int>]’:
test.cc:11:20: error: could not convert ‘std::index_sequence_for<long int>{}’ from ‘integer_sequence<[...],#‘nontype_argument_pack’ not supported by dump_expr#<expression error>>’ to ‘integer_sequence<[...],#‘nontype_argument_pack’ not supported by dump_expr#<expression error>>’
11 | C<long int>::call();
| ^
| |
| integer_sequence<[...],#‘nontype_argument_pack’ not supported by dump_expr#<expression error>>
test.cc:11:20: note: when instantiating default argument for call to ‘static void C<Args>::call(std::index_sequence<I ...>) [with long unsigned int ...I = {}; Args = {long int}; std::index_sequence<I ...> = std::integer_sequence<long unsigned int>]’
test.cc: In function ‘int main()’:
test.cc:11:20: error: could not convert ‘std::index_sequence_for<long int>{}’ from ‘integer_sequence<[...],#‘nontype_argument_pack’ not supported by dump_expr#<expression error>>’ to ‘integer_sequence<[...],#‘nontype_argument_pack’ not supported by dump_expr#<expression error>>’
任何想法?
更新:
我目前最好的解决方法是将默认参数分解为两个函数,如:
template<typename... Args>
class C {
static void call() {
_call(std::index_sequence_for<Args...>{});
}
template<size_t... I>
static void _call(std::index_sequence<I...>) {}
};
这似乎可以解决编译器错误(如果是这样的话)。
更新2:
下面的程序失败的原因与原来的程序相同:
template<typename T> void f(T x = 42) {}
int main() { f(); }
所以这是一个特性而不是一个bug。
一般来说,模板参数演绎+默认函数参数会造成很多麻烦。要简单地修复它,你可以这样做:
#include <utility>
#include <cstddef>
template<typename... Args>
class C {
public:
static void call() {
call_impl(std::index_sequence_for<Args...>{});
}
private:
template<size_t... I>
static void call_impl(std::index_sequence<I...> ) {
}
};
int main() {
C<long int>::call();
}
在c++ 20中,您还可以编写一个模板化的lambda来完成此操作,而无需创建新函数:
//...
static void call() {
return [&]<size_t... Is>(std::index_sequence<Is...>) {
/* your code goes here... */
}( std::index_sequence_for<Args...>{} );
}