【问题标题】:Inheritance and explicit constructors?继承和显式构造函数?
【发布时间】:2012-08-13 01:10:21
【问题描述】:

考虑以下代码:

template<typename T> class Base
{
    Base();
    Base(const Base<T>& rhs);
    template<typename T0> explicit Base(const Base<T0>&  rhs);
    template<typename T0, class = typename std::enable_if<std::is_fundamental<T0>::value>::type> Base(const T0& rhs);
    explicit Base(const std::string& rhs);
};

template<typename T> class Derived : Base<T>
{
    Derived();
    Derived(const Derived<T>& rhs);
    template<class T0> Derived(const T0& rhs) : Base(rhs); 
    // Is there a way to "inherit" the explicit property ?
    // Derived(double) will call an implicit constructor of Base
    // Derived(std::string) will call an explicit constructor of Base
};

有没有办法重新设计这段代码,使Derived 的所有构造函数都具有相同的显式/隐式属性?

【问题讨论】:

  • 继承的构造函数这样做。遗憾的是,它们尚未在我所知道的任何编译器上实现:(我很确定您可以手动执行此操作(可以轻松编写检测隐式/显式可构造性的特征,并且明智地使用 SFINAE 可以做到其余的),但我现在没有时间发布完整的答案。如果以后有时间时没有,我会这样做。
  • 请注意,您的 Derived 无法处理初始化列表。唯一适用于它们的解决方案是继承的ctors。

标签: c++ constructor c++11 explicit-constructor


【解决方案1】:

C++11 提供this as a feature。然而,甚至 GCC 还没有真正实现它。

实际实现的时候是这样的:

template<typename T> class Derived : Base<T>
{
    using Base<T>::Base;
};

话虽如此,这可能对您的情况没有帮助。继承的构造函数是一个全有或全无的命题。你得到所有的基类构造函数,完全使用它们的参数。另外,如果你定义一个与继承的具有相同签名的构造函数,你会得到一个编译错误。

【讨论】:

    【解决方案2】:

    检测 SFINAE 的隐式/显式可构造性:

    template<class T0, typename std::enable_if<
        std::is_convertible<const T0 &, Base<T>>::value, int>::type = 0>
        Derived(const T0& rhs) : Base<T>(rhs) { }
    template<class T0, typename std::enable_if<
        std::is_constructible<Base<T>, const T0 &>::value
        && !std::is_convertible<const T0 &, Base<T>>::value, int>::type = 0>
        explicit Derived(const T0& rhs) : Base<T>(rhs) { }
    

    使用std::is_convertible 检查隐式 可转换性这一事实,并使用std::is_constructible 来检查显式可转换性。

    编辑:使用来自boost::enable_if not in function signature 的解决方案修复了enable_if 模板参数。

    检查:

    Derived<int>{5};                            // allowed
    [](Derived<int>){}(5);                      // allowed
    Derived<int>{std::string{"hello"}};         // allowed
    [](Derived<int>){}(std::string{"hello"});   // not allowed
    

    【讨论】:

    • explicit 构造函数的约束可以用std::is_constructible&lt;Base&lt;T&gt;, T0 const&amp;&gt;::value &amp;&amp; !std::is_convertible&lt;T0 const&amp;, Base&lt;T&gt;&gt;::value 表示。 (您还想修正第一个约束:如果参数是T0 const&amp;,那么这就是您要检查的std::is_convertible,而不是T0。)
    猜你喜欢
    • 1970-01-01
    • 2014-11-22
    • 2018-10-10
    • 2016-03-24
    • 2017-05-20
    • 1970-01-01
    • 2011-12-27
    • 2017-11-17
    相关资源
    最近更新 更多