是否可以指定一个永远不会与基本类型(如int(匹配的模板参数?我极力反对模棱两可的说法。例如:
template<class T> void Function(const T& x) { SetString(x.GetString()); };
只有当T中有一个方法GetString时,这才有效,但如果编译器看到这个函数,即使T只是int,它也会尝试使用它。
方法1
您可以使用std::enable_if
,如下所示:
C++11
//this function template will not be used with fundamental types
template<class T> typename std::enable_if<!std::is_fundamental<T>::value>::type Function(const T& x)
{
SetString(x.GetString());
};
演示
C++17
template<class T> typename std::enable_if_t<!std::is_fundamental_v<T>> Function(const T& x)
{
SetString(x.GetString());
};
演示
方法2
我们可以使用SFINAE。在这里,我们使用decltype
和逗号运算符来定义函数模板的返回类型。
//this function template will work if the class type has a const member function named GetString
template <typename T> auto Function (T const & x) -> decltype( x.GetString(), void())
{
SetString(x.GetString());
};
演示
在这里,我们使用尾随返回类型语法来指定函数模板的返回类型。
如果问题是int
不支持GetString()
方法,那么您可以在模板类型有一个GetString() const
方法接受不带参数的调用时启用它,而不是为基本类型禁用该函数。
注意,GetString()
必须是const
,因为Function()
接收到const
引用,所以只有当GetString()
是const
方法时,才能在Function()
内部调用GetString()
。
下面是一个完整的编译示例。观察bar1
和bar2
情况下的故障
#include <string>
void SetString (std::string const &)
{ }
struct foo // class with a conformat GetString method
{ std::string GetString () const { return "abc"; } };
struct bar1 // class with a not conformant (not const) GetString method
{ std::string GetString () { return "123"; } };
struct bar2 // class with a not conformant (require a int) GetString method
{ std::string GetString (int) const { return "123"; } };
struct bar3 // class without a GetString method
{ };
template <typename T>
auto Function (T const & x) -> decltype( x.GetString(), void())
{ SetString(x.GetString()); }
int main()
{
Function(foo{}); // compile
// Function(bar1{}); // compilation error (GetString isn't const)
// Function(bar2{}); // compilation error (GetString require a int)
// Function(bar3{}); // compilation error (no GetString method)
// Function(0); // compilation error (no GetString method)
}