【问题标题】:Using member declaration with enable_if?使用带有 enable_if 的成员声明?
【发布时间】:2016-03-13 07:27:21
【问题描述】:

我需要有条件的 using 成员声明。

template <bool> struct B;
template <> struct B<true> { void foo(); };
template <> struct B<false> { };

template <typename T>
struct A : public B<is_default_constructible<T>::value> {
    using B<is_default_constructible<T>::value>::foo();

    void foo(int) {}
};

这显然行不通,因为B&lt;bool&gt;::foo 没有定义 在一半的情况下。我怎样才能做到这一点?有B&lt;&gt;::foo() 在 foo(int) 旁边的 A&lt;T&gt; 范围内可见?

感谢您的帮助

【问题讨论】:

  • 您到底想要什么? A::foo(void) 仅在未定义 B&lt;&gt;::foo(void) 时才定义?
  • @RichardHodges 我读的正好相反:A::foo(void) 应该在定义 B&lt;&gt;::foo(void) 的情况下定义。
  • 确切地说,如果 T 是默认可构造的,我想要 A::foo(void) (因此定义了 B::foo(void),因为 B);

标签: c++ c++11 visual-studio-2012 visual-c++ visual-c++-2012


【解决方案1】:

这是我的解决方案。我确信它不会是最好的,但它可以完成工作。

struct A {
    void foo(int) {}
};

struct A 应该包含您想要在这两种情况下定义的方法。

template <bool> struct B;
template <> struct B<false> : A {};
template <> struct B<true> : A { 
    using A::foo;
    void foo() {} 

};

B&lt;false&gt; 的情况下,仅定义void foo(int)。在B&lt;true&gt; 的情况下,void foo(int)void foo() 都被定义。

template <typename T>
struct C : public B<is_default_constructible<T>::value> {};

现在我不必担心在某些情况下没有定义B&lt;is_default_constructible&lt;T&gt;::value&gt;::foo()

class D { D() = delete; };

int main()
{
    C<int> c1;
    c1.foo(1234);
    c1.foo();
    // both methods are defined for C<int>

    C<D> c2;
    c2.foo(1234);
    // c2.foo(); // undefined method

    return 0;
}

【讨论】:

    【解决方案2】:

    使用专业化。

    enable_if 不能用于此。你也需要专门化struct A

    #include <type_traits>
    
    template <bool> struct B;
    template <> struct B<true> { void foo(); };
    template <> struct B<false> { };
    
    template <typename T, bool default_constructible = std::is_default_constructible<T>::value>
    struct A : public B<default_constructible> {
        using B<default_constructible>::foo;
    
        void foo(int) {}
    };
    
    template<typename T>
    struct A<T, false> : public B<false> {
        void foo(int) {}
    };
    

    避免 foo(int) 的重复代码

    如果foo(int) 在这两种情况下都具有相同的功能,您可能希望从另一个基础结构派生它:

    #include <type_traits>
    
    template <bool> struct B;
    template <> struct B<true> { void foo(); };
    template <> struct B<false> { };
    
    template<typename T>
    struct C {
      void foo(int) {}
    };
    
    template <typename T, bool default_constructible = std::is_default_constructible<T>::value>
    struct A : public B<default_constructible>, public C<T> {
        using B<default_constructible>::foo;
        using C<T>::foo;
    };
    
    template<typename T>
    struct A<T, false> : public B<false>, public C<T> {
        using C<T>::foo;
    };
    

    删除那个丑陋的布尔

    最后,要从struct A 的模板参数中删除该布尔值,您可能希望将选择foo 的重载的责任转发给基类。这还具有不为您可能想要添加的其他struct A 成员重复代码的优点。

    #include <type_traits>
    
    template <bool> struct B;
    template <> struct B<true> { void foo(); };
    template <> struct B<false> { };
    
    template<typename T>
    struct C {
      void foo(int) {}
    };
    
    template <typename T, bool default_constructible = std::is_default_constructible<T>::value>
    struct base_A : public B<default_constructible>, public C<T> {
        using B<default_constructible>::foo;
        using C<T>::foo;
    };
    
    template<typename T>
    struct base_A<T, false> : public B<false>, public C<T> {
        using C<T>::foo;
    };
    
    template <typename T>
    struct A : public base_A<T> {
        // Other members.
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-15
      • 1970-01-01
      • 2013-09-07
      • 2019-08-04
      • 2012-06-22
      • 2020-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多