这两个非可变函数模板可以编译:
template <typename T, typename U>
typename std::enable_if<std::is_same<U, int>::value, void>::
type testFunction(T a, U b) {
std::cout << "b is integer\n";
}
template <typename T, typename U>
typename std::enable_if<std::is_same<U, float>::value, void>::
type testFunction(T a, U b) {
std::cout << "b is float\n";
}
但是,类似的可变参数模板不能编译:
template <typename T, typename... U>
typename std::enable_if<std::is_same<U, int>::value, void>::
type testFunction(T a, U... bs) {
std::cout << "bs are integers\n";
}
template <typename T, typename... U>
typename std::enable_if<std::is_same<U, float>::value, void>::
type testFunction(T a, U... bs) {
std::cout << "bs are floats\n";
}
也许我正在尝试做一些无法做到的事情。我知道使用初始化列表可以实现类似的功能,但我想避免使用初始化列表参数所需的大括号。
答案 0 :(得分:7)
是。您可以在C ++ 17中使用fold expression:
template <typename T, typename... U>
typename std::enable_if<(std::is_same<U, float>::value && ...), void>::
type testFunction(T a, U... bs) {
std::cout << "bs are floats\n";
}
在C ++ 11中,您可以重新实现std::conjunction
:
template<class...> struct conjunction : std::true_type { };
template<class B1> struct conjunction<B1> : B1 { };
template<class B1, class... Bn>
struct conjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
template <typename T, typename... U>
typename std::enable_if<
std::conjunction_v<std::is_same<U, float>...>,
void
>::type testFunction(T a, U... bs) {
std::cout << "bs are floats\n";
}
答案 1 :(得分:1)
如果您受C ++ 11约束并希望保持代码可读,则可以实现与is_same
相匹配的简单等效类型:
template <typename Ref, typename T1, typename... TN>
struct all_match;
template <typename Ref, typename T>
struct all_match<Ref,T>
{
static constexpr bool value = std::is_same<T,Ref>::value;
};
template <typename Ref, typename T1, typename... TN>
struct all_match
{
static constexpr bool value = std::is_same<T1,Ref>::value && all_match<Ref, TN...>::value;
};
然后(注意,引用类型先行):
template <typename T, typename... U>
typename std::enable_if<all_match<int, U...>::value, void>::
type testFunction(T a, U... bs) {
std::cout << "bs are integers\n";
}
现场演示:click。
C ++ 17引入了fold expression,它允许您在二元运算符上折叠参数包(...
)。您可以使用它轻松地对参数包中的所有类型应用std::is_same<>
,然后and
值:
template <typename T, typename... U>
typename std::enable_if<(std::is_same<U, float>::value && ...), void>::
type testFunction(T a, U... bs) {
std::cout << "bs are floats\n";
}
template <typename T, typename... U>
typename std::enable_if<(std::is_same<U, int>::value && ...), void>::
type testFunction(T a, U... bs) {
std::cout << "bs are ints\n";
}
您可以查看此版本here的演示。
答案 2 :(得分:0)
或者你可以简单地使用额外的可变参数pack
来测试所有模板参数是否相同并且等于给定类型(C ++ 11):
#include <type_traits>
#include <iostream>
template <class...>
struct pack { };
template <typename T, typename... U>
typename std::enable_if<std::is_same<pack<int, U...>, pack<U..., int>>::value, void>::
type testFunction(T a, U... bs) {
std::cout << "bs are integers\n";
}
template <typename T, typename... U>
typename std::enable_if<std::is_same<pack<float, U...>, pack<U..., float>>::value, void>::
type testFunction(T a, U... bs) {
std::cout << "bs are floats\n";
}
int main() {
testFunction(1, 2, 3, 4, 5);
testFunction(1, 2.0f, 3.5f, 4.4f, 5.3f);
}
输出:
bs are integers
bs are floats