C ++ Enable方法基于模板元组的arity
C++ Enable method based on arity of template tuple
我试图在模板化 class 中有选择地启用一个方法,仅当元组模板参数具有特定数量时。我一直在尝试各种组合,但到目前为止找不到让下面的代码编译的方法。
本质上,当我用一个只有两个元素的元组实例化 class foo 时,我希望启用第一个“void print()”方法,而当我实例化 foo 时其中包含三个元素的元组我希望启用第二个“void print()”方法。
注意:这只是一个抽象的例子,是从我试图解决的一个更复杂的问题提炼出来的。我也能够使用基于两个特定元组的部分模板专业化来工作。但是我真的很想了解“enable_if”,我希望它能让我的代码“更简单”。
谢谢
// g++ -std=c++14 a.cc
#include <tuple>
#include <type_traits>
#include <iostream>
using namespace std;
template <class Tuple>
class foo {
public:
Tuple t;
foo(Tuple ta) : t(ta) {
cout<<"constructor\n";
}
//How do I enable this print ONLY if arity of input tuple is 2 ???
typename std::enable_if< std::tuple_size<Tuple>::value == 2, void >::type
print(){
cout<<get<0>(t)<<":"<<get<1>(t)<<"\n";
}
// enable ONLY if arity 3 ???
typename std::enable_if< std::tuple_size<Tuple>::value == 3, void >::type
print(){
cout<<get<0>(t)<<":"<<get<1>(t)<<"::"<<get<1>(t)<<"\n";
}
};
int main(int argc, char**argv) {
typedef tuple<int, double> t2_type;
typedef tuple<int, double, float> t3_type;
t2_type t2(1,2.0);
t3_type t3(100,100.0,2.3);
foo<t2_type> f2(t2);
foo<t3_type> f3(t3);
f2.print();
f3.print();
}
上面的具体代码这里是编译错误:
% g++ -std=c++14 a.cc
a.cc:25:3: error: ‘typename std::enable_if<(std::tuple_size<_Tp>::value == 3), void>::type foo<Tuple>::print()’ cannot be overloaded
print(){
^
a.cc:19:3: error: with ‘typename std::enable_if<(std::tuple_size<_Tp>::value == 2), void>::type foo<Tuple>::print()’
print(){
^
a.cc: In instantiation of ‘class foo<std::tuple<int, double, float> >’:
a.cc:38:21: required from here
a.cc:19:3: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
a.cc: In function ‘int main(int, char**)’:
a.cc:41:6: error: ‘class foo<std::tuple<int, double, float> >’ has no member named ‘print’
f3.print();
^
GCC 详细信息,尽管这应该与编译器无关;
% g++ -v
gcc version 4.9.4 (GCC)
解决方案 1 来自以下答案:
#include <tuple>
#include <type_traits>
#include <iostream>
using namespace std;
template <class Tuple>
class foo {
public:
Tuple t;
foo(Tuple ta) : t(ta) {
cout<<"constructor\n";
}
template <typename T = Tuple>
typename std::enable_if< std::tuple_size<T>::value == 2, void >::type
print(){
cout<<get<0>(t)<<":"<<get<1>(t)<<"\n";
}
// enable ONLY if arity 3 ???
template <typename T = Tuple>
typename std::enable_if< std::tuple_size<T>::value == 3, void >::type
print(){
cout<<get<0>(t)<<":"<<get<1>(t)<<"::"<<get<1>(t)<<"\n";
}
};
int main(int argc, char**argv) {
typedef tuple<int, double> t2_type;
typedef tuple<int, double, float> t3_type;
t2_type t2(1,2.0);
t3_type t3(100,100.0,2.3);
foo<t2_type> f2(t2);
foo<t3_type> f3(t3);
f2.print();
f3.print();
}
enable_if 不能基于 class-level 模板参数。它必须在 SFINAE 工作的函数实例化时被推导。将模板参数添加到 print 应该可以解决问题。对于 size 2 的打印函数,它看起来像下面这样
template<typename TupleParam>
typename std::enable_if< std::is_same<Tuple, TupleParam>::value &&
std::tuple_size<TupleParam>::value == 2, void >::type
print(){
cout<<get<0>(t)<<":"<<get<1>(t)<<"\n";
}
您需要制作 print
模板才能使用 enable_if
。为此,您可以只使用 class 模板参数:
template <typename T = Tuple>
typename std::enable_if< std::tuple_size<T>::value == 2, void >::type
print() {
cout<<get<0>(t)<<":"<<get<1>(t)<<"\n";
}
template <typename T = Tuple>
typename std::enable_if< std::tuple_size<T>::value == 3, void >::type
print() {
cout<<get<0>(t)<<":"<<get<1>(t)<<"::"<<get<1>(t)<<"\n";
}
这是一个demo。
我试图在模板化 class 中有选择地启用一个方法,仅当元组模板参数具有特定数量时。我一直在尝试各种组合,但到目前为止找不到让下面的代码编译的方法。
本质上,当我用一个只有两个元素的元组实例化 class foo 时,我希望启用第一个“void print()”方法,而当我实例化 foo 时其中包含三个元素的元组我希望启用第二个“void print()”方法。
注意:这只是一个抽象的例子,是从我试图解决的一个更复杂的问题提炼出来的。我也能够使用基于两个特定元组的部分模板专业化来工作。但是我真的很想了解“enable_if”,我希望它能让我的代码“更简单”。
谢谢
// g++ -std=c++14 a.cc
#include <tuple>
#include <type_traits>
#include <iostream>
using namespace std;
template <class Tuple>
class foo {
public:
Tuple t;
foo(Tuple ta) : t(ta) {
cout<<"constructor\n";
}
//How do I enable this print ONLY if arity of input tuple is 2 ???
typename std::enable_if< std::tuple_size<Tuple>::value == 2, void >::type
print(){
cout<<get<0>(t)<<":"<<get<1>(t)<<"\n";
}
// enable ONLY if arity 3 ???
typename std::enable_if< std::tuple_size<Tuple>::value == 3, void >::type
print(){
cout<<get<0>(t)<<":"<<get<1>(t)<<"::"<<get<1>(t)<<"\n";
}
};
int main(int argc, char**argv) {
typedef tuple<int, double> t2_type;
typedef tuple<int, double, float> t3_type;
t2_type t2(1,2.0);
t3_type t3(100,100.0,2.3);
foo<t2_type> f2(t2);
foo<t3_type> f3(t3);
f2.print();
f3.print();
}
上面的具体代码这里是编译错误:
% g++ -std=c++14 a.cc
a.cc:25:3: error: ‘typename std::enable_if<(std::tuple_size<_Tp>::value == 3), void>::type foo<Tuple>::print()’ cannot be overloaded
print(){
^
a.cc:19:3: error: with ‘typename std::enable_if<(std::tuple_size<_Tp>::value == 2), void>::type foo<Tuple>::print()’
print(){
^
a.cc: In instantiation of ‘class foo<std::tuple<int, double, float> >’:
a.cc:38:21: required from here
a.cc:19:3: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
a.cc: In function ‘int main(int, char**)’:
a.cc:41:6: error: ‘class foo<std::tuple<int, double, float> >’ has no member named ‘print’
f3.print();
^
GCC 详细信息,尽管这应该与编译器无关;
% g++ -v
gcc version 4.9.4 (GCC)
解决方案 1 来自以下答案:
#include <tuple>
#include <type_traits>
#include <iostream>
using namespace std;
template <class Tuple>
class foo {
public:
Tuple t;
foo(Tuple ta) : t(ta) {
cout<<"constructor\n";
}
template <typename T = Tuple>
typename std::enable_if< std::tuple_size<T>::value == 2, void >::type
print(){
cout<<get<0>(t)<<":"<<get<1>(t)<<"\n";
}
// enable ONLY if arity 3 ???
template <typename T = Tuple>
typename std::enable_if< std::tuple_size<T>::value == 3, void >::type
print(){
cout<<get<0>(t)<<":"<<get<1>(t)<<"::"<<get<1>(t)<<"\n";
}
};
int main(int argc, char**argv) {
typedef tuple<int, double> t2_type;
typedef tuple<int, double, float> t3_type;
t2_type t2(1,2.0);
t3_type t3(100,100.0,2.3);
foo<t2_type> f2(t2);
foo<t3_type> f3(t3);
f2.print();
f3.print();
}
enable_if 不能基于 class-level 模板参数。它必须在 SFINAE 工作的函数实例化时被推导。将模板参数添加到 print 应该可以解决问题。对于 size 2 的打印函数,它看起来像下面这样
template<typename TupleParam>
typename std::enable_if< std::is_same<Tuple, TupleParam>::value &&
std::tuple_size<TupleParam>::value == 2, void >::type
print(){
cout<<get<0>(t)<<":"<<get<1>(t)<<"\n";
}
您需要制作 print
模板才能使用 enable_if
。为此,您可以只使用 class 模板参数:
template <typename T = Tuple>
typename std::enable_if< std::tuple_size<T>::value == 2, void >::type
print() {
cout<<get<0>(t)<<":"<<get<1>(t)<<"\n";
}
template <typename T = Tuple>
typename std::enable_if< std::tuple_size<T>::value == 3, void >::type
print() {
cout<<get<0>(t)<<":"<<get<1>(t)<<"::"<<get<1>(t)<<"\n";
}
这是一个demo。