【问题标题】:Using enable_if on virtual functions在虚函数上使用 enable_if
【发布时间】:2019-08-04 09:31:02
【问题描述】:
#include <type_traits>

class Base {
public:
    virtual bool f() {
        return true;
    }
};

template<typename T>
class Derived : public Base {
    std::enable_if_t< std::is_copy_constructible<T>::value, bool > f() override {
        return true;
    }

    std::enable_if_t< !std::is_copy_constructible<T>::value, bool > f() override {
        return false;
    }
};

以上代码无法编译。由于某种原因,我无法理解,编译器将这两个函数视为相同的重载,然后再被 SFINAE 删除。

然而,我不明白我该如何解决这个问题。我找到的文档state 我应该在函数上使用模板。但是,这不起作用,因为该函数是虚拟的。

我尝试通过调用非虚拟函数来解决问题,但我也无法编译:

template<typename T>
class Derived : public Base {
    virtual bool f() override {
        return f_impl();
    }

private:
    template< std::enable_if_t< std::is_copy_constructible<T>::value > = 0 >
    bool f_impl() {
        return true;
    }

    template< std::enable_if_t< !std::is_copy_constructible<T>::value > >
    bool f_impl() {
        return false;
    }
};

int main() {
    Derived<int> a;

    std::cout<<a.f()<<"\n";
}

编译失败:

so.cpp: In instantiation of ‘class Derived<int>’:
so.cpp:29:18:   required from here
so.cpp:18:10: error: ‘std::enable_if<true, void>::type’ {aka ‘void’} is not a valid type for a template non-type parameter

我显然在这里做错了什么,但我不知道什么是正确的方法。

【问题讨论】:

  • 为什么不直接返回一个值bool f() override { return std::is_copy_constructible&lt;T&gt;::value; }
  • 因为这是一个简化的例子。实际上,我需要做两件截然不同的事情。

标签: c++ templates template-meta-programming sfinae enable-if


【解决方案1】:

很遗憾,您不能这样做。 SFINAE 使用模板;例如以下代码从您的第二个示例作品中修改。

template< typename X = T>
std::enable_if_t< std::is_copy_constructible<X>::value, bool >
f_impl() {
    return true;
}

template< typename X = T>
std::enable_if_t< !std::is_copy_constructible<X>::value, bool >
f_impl() {
    return false;
}

LIVE

但是virtual 函数不能是模板,仅此而已。

【讨论】:

  • 你能详细说明为什么这个std::is_copy_constructible&lt;T&gt; 的解决方案不起作用吗?
  • @ShacharShemesh std::enable_if 应该依赖于函数模板本身的模板参数。否则,SFINAE 将不起作用; f_impl 都将被实例化,并且其中任何一个都肯定是格式错误的。
【解决方案2】:

使用if constexpr 可以在编译时在函数内部进行分支,因此函数可以保留virtual

bool f() override
{
    if constexpr(std::is_copy_constructible<T>::value)
    {
        return true;
    }
    else
    {
        return false;
    }
}

【讨论】:

  • 我可以做if constexpr(false) nonExstingFunction(); 吗?因为这是一个简化的例子。
  • @ShacharShemesh 这将类似于非实例化模板 - 非活动分支不会出现在编译函数的主体中,但语法应该是有效的。
  • 由于 if 的 true 分支需要实际调用复制构造函数,恐怕这个解决方案对我不起作用。我在那里,希望 C++ 引入 static_if 而我没有注意到......
  • @ShacharShemesh 确实是static_if,如果对您不起作用,那么带有模板的变体也将不起作用
  • 所以如果我理解正确,if constexprfalse 侧需要在语法上正确,但不需要在语义上正确。它可能引用不存在的函数和变量?
猜你喜欢
  • 2017-03-29
  • 1970-01-01
  • 2011-06-20
  • 2018-08-23
  • 2018-03-18
  • 2022-11-20
  • 2013-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多