Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我是否可以重用同一个模板来声明/定义多个内容(而不复制模板代码)?_C++_Templates - Fatal编程技术网

C++ 我是否可以重用同一个模板来声明/定义多个内容(而不复制模板代码)?

C++ 我是否可以重用同一个模板来声明/定义多个内容(而不复制模板代码)?,c++,templates,C++,Templates,我目前正在编写一个类,它有一些奇特的模板来定义它的一些成员,但其中一些模板是完全相同的。考虑下面的代码(这些都是类成员): 模板 T get()const{return convert_self_to_int()} 模板 T get()const{return convert_self_to_string();} 模板 运算符T()常量{return get();} 模板 运算符T()常量{return get();} 正如您所看到的,我有一个名为get的模板成员函数,它使用长且有点难读的模板

我目前正在编写一个类,它有一些奇特的模板来定义它的一些成员,但其中一些模板是完全相同的。考虑下面的代码(这些都是类成员):

模板
T get()const{return convert_self_to_int()}
模板
T get()const{return convert_self_to_string();}
模板
运算符T()常量{return get();}
模板
运算符T()常量{return get();}
正如您所看到的,我有一个名为
get
的模板成员函数,它使用长且有点难读的模板代码

这一部分并不是问题的关键,但这里有一个对所有这些奇特模板的简要说明:
get
是一个 可以以两种格式之一返回数据:如果模板参数
T
为 一种类型,可将
int
转换为该类型,然后再转换为整数 返回数据的表示形式(从而触发转换 到请求的类型,我们知道这是可能的)。如果
T
是什么 它可以由
字符串
构造,然后是
字符串
返回数据的表示形式(再次触发 从
字符串构建
T
)。任何其他类型的 属于这些类别只会导致编译时错误, 这正是这段代码的目的

此类还定义了简单的转换运算符,这些运算符是按照
get
编写的


现在,由于这些操作符使用与
get
的相应定义完全相同的模板,我能以某种方式避免复制所有讨厌的模板代码吗?我是否可以重复使用一行模板代码来定义多个内容,从而使代码更具可读性?

您只需使用SFINAE将
操作符T()
转发到
get
。这样,您只需要一个
操作符T()


不幸的是,这在叮当声中是行不通的,所以我只建议翻转订单。将
运算符T()设置为SFINAE-d:

template <class T, std::enable_if_t<std::is_convertible<int, T>::value, int> = 0>
operator T() const { return convert_self_to_int(); }

template <class T, std::enable_if_t<std::is_convertible<std::string, T>::value, int> = 0>
operator T() const { return convert_self_to_string(); }

这里的优点是我们没有复制任何东西,
std::is_convertible
类型特征将正常工作-因为
操作符T()
是SFINAE-d。对
get()
的测试将失败,但这似乎不像是通常可以测试的

您可以在Templates中使用布尔运算您知道默认的模板类型参数不是函数签名的一部分,因此不能在SFINAE重载中使用?我也从堆栈溢出中学到了这种模板重载。那么这是错的吗?但不管怎样,我认为我的问题仍然是正确的,即使我的代码可能还有其他问题。@adam10603,你要么误解了你所学到的东西,要么是从错误的源代码中学到的。那么我如何正确地编写这个问题呢?我只想为满足某个条件的类型定义一个,为满足另一个条件的类型定义另一个,并为两者都不满足的类型触发一个错误。就我所测试的而言,它的工作原理与之完全相同。Parameter pack的绝妙技巧!以前没见过,没想过。你给转换操作符的解决方案在Xcode中给了我一个错误,说:成员访问不完整的类型“className”。是的,我确实用实际名称替换了className。我很困惑。不过,模板参数的技巧很好:)@adam10603嗯。好的,一分钟。而clang不喜欢这个参数pack@adam10603如果翻转
操作符T()
get()
(请参阅更新),它会更好一些,并且可以在两个编译器上工作。但仍然不能令人满意。
template <class T, std::enable_if_t<std::is_convertible<int, T>::value, int> = 0>
T get() const { return convert_self_to_int(); }

template <class T, std::enable_if_t<std::is_convertible<std::string, T>::value, int> = 0>
T get() const { return convert_self_to_string(); }
template <class T, std::enable_if_t<std::is_convertible<int, T>::value, int> = 0>
operator T() const { return convert_self_to_int(); }

template <class T, std::enable_if_t<std::is_convertible<std::string, T>::value, int> = 0>
operator T() const { return convert_self_to_string(); }
template <class T> T get() const { return operator T(); }