C++ 模板参数限制为 类(不是基本类型)
C++ template argument limited to classes (not basic types)
是否可以指定一个永远不会匹配基本类型(例如 int)的模板参数?我正在与歧义作斗争。例如:
template<class T> void Function(const T& x) { SetString(x.GetString()); };
只有在 T 中有 GetString 方法时才有效,但如果编译器看到此函数,它会尝试使用它,例如即使 T 只是 int。
方法一
您可以使用 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());
};
方法二
我们可以利用SFINAE。这里我们使用decltype
和逗号运算符来定义函数模板的return类型
//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());
};
这里我们使用了尾随return类型语法来指定函数模板的return类型。
如果 int
不支持 GetString()
方法的问题,也许不是禁用基本类型的功能,您可以在(且仅当)模板类型时启用它有一个 GetString() const
方法接受不带参数的调用。
观察GetString()
一定是const
,因为Function()
收到一个const
引用,所以可以在Function()
里面调用GetString()
仅当 GetString()
是 const
方法时。
下面是一个完整的编译示例。观察 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)
}
是否可以指定一个永远不会匹配基本类型(例如 int)的模板参数?我正在与歧义作斗争。例如:
template<class T> void Function(const T& x) { SetString(x.GetString()); };
只有在 T 中有 GetString 方法时才有效,但如果编译器看到此函数,它会尝试使用它,例如即使 T 只是 int。
方法一
您可以使用 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());
};
方法二
我们可以利用SFINAE。这里我们使用decltype
和逗号运算符来定义函数模板的return类型
//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());
};
这里我们使用了尾随return类型语法来指定函数模板的return类型。
如果 int
不支持 GetString()
方法的问题,也许不是禁用基本类型的功能,您可以在(且仅当)模板类型时启用它有一个 GetString() const
方法接受不带参数的调用。
观察GetString()
一定是const
,因为Function()
收到一个const
引用,所以可以在Function()
里面调用GetString()
仅当 GetString()
是 const
方法时。
下面是一个完整的编译示例。观察 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)
}