使用成员声明和enable_if?

时间:2015-12-08 11:33:54

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

我需要使用成员声明的条件。

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<bool>::foo未定义 一半的情况。我怎样才能做到这一点?拥有B<>::foo() 在foo(int)旁边的A<T>范围内可见?

感谢您的帮助

2 个答案:

答案 0 :(得分:0)

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

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<false>,则只定义void foo(int)。如果是B<true>,则void foo(int)void foo()都已定义。

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

现在我不必担心在某些情况下B<is_default_constructible<T>::value>::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;
}

答案 1 :(得分:0)

使用专业化。

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的模板参数中删除该bool,您可能希望将选择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.
};