C++模板参数仅限于类(非基本类型)

发布于 2025-01-11 01:19:34 字数 232 浏览 0 评论 0原文

是否可以指定一个永远不会与基本类型(例如 int)匹配的模板参数?我正在大力对抗歧义。例如:

template<class T> void Function(const T& x) { SetString(x.GetString()); };

只有当 T 中有 GetString 方法时才有效,但是如果编译器看到这个函数,它会尝试使用它,即使 T 只是 int 。

Is it possible specify a template argument, that would never match to a basic type, such as an int? I'm heavily fighting ambiguities. So for example:

template<class T> void Function(const T& x) { SetString(x.GetString()); };

That would work only if there's a method GetString in T, but if the compiler sees this function, it tries to uses it even if T is just int for example.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

羁绊已千年 2025-01-18 01:19:34

方法一

可以使用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()); 
    
};

Demo

C++17

template<class T> typename std::enable_if_t<!std::is_fundamental_v<T>> Function(const T& x) 
{ 
    SetString(x.GetString()); 
    
};

Demo

方法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());   
};

演示

这里我们使用尾随返回类型语法来指定函数模板。

Method 1

You can use std::enable_if as shown below:

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()); 
    
};

Demo

C++17

template<class T> typename std::enable_if_t<!std::is_fundamental_v<T>> Function(const T& x) 
{ 
    SetString(x.GetString()); 
    
};

Demo

Method 2

We can make use of SFINAE. Here we use decltype and the comma operator to define the return type of the function template.

//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());   
};

Demo

Here we've used trailing return type syntax to specify the return type of the function template.

作死小能手 2025-01-18 01:19:34

如果问题是 int 不支持 GetString() 方法,也许您可​​以启用它,而不是禁用基本类型的函数(且仅当)模板类型有一个 GetString() const 方法,接受不带参数的调用。

请注意,GetString() 必须为 const,因为 Function() 接收 const 引用,因此您可以调用仅当 GetString()const 方法时,Function() 内的 GetString() 才有效。

下面是一个完整的编译示例。观察 bar1bar2 情况下的失败

#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)
}

If the problem i that int doesn't support a GetString() method, maybe instead of disable the function for fundamental types, you could enable it if (and only if) the template type has a GetString() const method accepting a call without arguments.

Observe that GetString() must be const, because Function() receive a const reference, so you can call GetString() inside Function() only if GetString() is a const method.

The following is a full compiling example. Observe the failure in the bar1 and bar2 cases

#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)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文