我在 C++17 中有一个模板函数,其中 N 个第一个参数需要是整型,并且应该在模板替换期间检查这一点。 (对于不满足条件的参数,模板函数不应该存在,因此函数体中的
static_assert()
不起作用。)
它是类的构造函数,因此 SFINAE 是在模板参数中完成的。
对于固定 N = 2,这有效:
struct A {
template<class Arg1, class Arg2, class... OtherArgs,
std::enable_if_t<(std::is_integral_v<Arg1> && std::is_integral_v<Arg2>), int> = 0
>
A(Arg1 arg1, Arg2 arg2, OtherArgs... otherArgs)
};
然而,当
N
是模板参数时,似乎没有明显的方法。
要检查所有参数是否是整数,这有效:
template<std::size_t N>
struct A {
template<class... Args,
std::enable_if_t<std::conjunction_v<std::is_integral<Args>...>, int> = 0
>
A(Args... args)
};
有没有像
INDEX_OF
这样的工具,可以获取参数包中参数的索引,这样is_integral
只需要对前N个参数为真?
template<std::size_t N>
struct A {
template<class... Args,
std::enable_if_t<std::conjunction_v<
std::disjunction<
std::bool_constant< (INDEX_OF(Args) >= N) >,
std::is_integral<Args>
>...
>, int> = 0
>
A(Args... args)
};
您可以创建 constexpr 函数:
template <std::size_t N, typename... Ts>
static constexpr bool first_are_integral()
{
constexpr bool bools[] = {std::is_integral_v<Ts>...};
return std::all_of(std::begin(bools), std::begin(bools) + N,
[](bool b){ return b; });
}
然后
template <class... Args,
std::enable_if_t<first_are_integral<N, Args...>(), int> = 0
>
A(Args...){ /*...*/ }