SFINAE用于类方法

时间:2018-06-01 17:40:48

标签: c++ oop templates c++14 sfinae

文章https://www.fluentcpp.com/2018/05/15/make-sfinae-pretty-1-what-value-sfinae-brings-to-code/https://www.fluentcpp.com/2018/05/18/make-sfinae-pretty-2-hidden-beauty-sfinae/解释了如何将SFINAE用于类方法。该类的第一个实现如下:

id

如果template<typename T> class MyClass { public: void f(T const& x); void f(T&& x); }; 是参考,为了防止使用第二个函数f,本文提出了以下解决方案:

T

通过template<typename T> class MyClass { public: void f(T const& x){} template<typename T_ = T, typename = std::enable_if_t<!std::is_reference_v<T_>>> void f(T&& x){} }; 替换方法的返回类型会更容易/更清洁吗?所以课程如下:

std::enable_if

2 个答案:

答案 0 :(得分:2)

首先,你的技术不起作用。 T MyClass enable_if_t<false>中的template<class T_=T> std::enable_if_t<!std::is_reference_v<T_>>> f(T_&& x){} T_是固定类型。没有进行替换,所以这不是替换失败,它只是一个不正确的签名。

您可以使用

在某种程度上修复它
settings: {
   purchaseAmount: null,
   pendingTime: 500,
   validationResult: !0000
}

现在,这种技术(使用返回值)在构造函数上不起作用(A),并且(B)当你想推导出返回类型时。

它还将返回类型与SFINAE代码混合;两者无关。

除此之外,这种技术和您正在复制的原始技术都与“所有模板必须具有有效的实例化”有一些可疑的交互。我还不清楚这是否适用于固定模板类实例化的每个模板方法;如果是这样,那么你必须确保一些validationResult:!0000会使身体有效。

答案 1 :(得分:1)

  

用enable_if替换方法的返回类型会不会更容易/更清晰?

我想是个人品味的问题。

无论如何,请记住你的例子

std::enable_if_t<!std::is_reference_v<T>>> f(T&& x){}

不起作用,因为SFINAE在特定方法的模板上工作。因此,同样对于您的示例,您必须使用T_(我称之为U)模板类型,条件std::is_reference必须评估U,而不是{{1 }}

T

无论如何,对于这两种解决方案都存在“劫持”风险:您可以绕过表示template <typename U = T> std::enable_if_t<!std::is_reference_v<U>> f(T&& x){} 类型的测试

U

为避免劫持风险,您还必须强制myClassObject.template f<void>(aReference); T属于同一类型

U