我正在尝试C++ 11的新功能。在我的设置中,我真的很想使用继承的构造函数,但是不幸的是,还没有编译器实现这些构造函数。因此,我试图模拟相同的行为。我可以这样写:

template <class T>
class Wrapper : public T {
    public:
    template <typename... As>
    Wrapper(As && ... as) : T { std::forward<As>(as)... } { }
    // ... nice additions to T ...
};

大部分时间都有效。有时,使用Wrapper类的代码必须使用SFINAE来检测如何构造这种Wrapper<T>。但是,存在以下问题:就重载解析而言,Wrapper<T>的构造函数将接受任何参数-但是,如果无法使用T类型构造enable_if,则编译会失败(并且SFINAE不会涵盖)。

我试图使用T有条件地启用构造函数模板的不同实例化
    template <typename... As, typename std::enable_if<std::is_constructible<T, As && ...>::value, int>::type = 0>
    Wrapper(As && ... as) // ...

只要:
  • public的适当构造函数是T
  • sizeof()不是抽象的

  • 我的问题是:如何摆脱以上两个约束?

    我试图通过检查(使用SFINAE和new T(std::declval<As &&>()...))来克服第一个问题,即Wrapper<T>Wrapper中是否是格式正确的。但这当然是行不通的,因为派生类可以使用其基类的 protected 构造函数的唯一方法是在成员初始化列表中。

    对于第二个,我什么都不知道,这是我需要的,因为有时T实现了ojit_code的抽象功能,使其成为完整的类型。

    我想要一个解决方案:
  • 根据标准
  • 是正确的
  • 适用于gcc-4.6。*,gcc-4.7。*或clang-3。*中的任何一种

    谢谢!

    最佳答案

    这对我本地的GCC似乎效果很好(4.7,rubenvb提供)。但是,在ideone上的GCC会打印一些“已实现”的编译器内部错误。

    我不得不公开Experiment类的“实现细节”,因为出于某些原因(闻起来像个错误),我的GCC版本提示它们是私有(private)的,即使只有类本身使用了它。

    #include <utility>
    
    template<typename T, typename Ignored>
    struct Ignore { typedef T type; };
    
    struct EatAll {
      template<typename ...T>
      EatAll(T&&...) {}
    };
    
    template<typename T>
    struct Experiment : T {
    public:
      typedef char yes[1];
      typedef char no[2];
    
      static void check1(T const&);
      static void check1(EatAll);
    
      // if this SFINAE fails, T accepts it
      template<typename ...U>
      static auto check(int, U&&...u)
        -> typename Ignore<no&,
            decltype(Experiment::check1({std::forward<U>(u)...}))>::type;
    
      template<typename ...U>
      static yes &check(long, U&&...);
    
    public:
      void f() {}
      template<typename ...U,
               typename std::enable_if<
                 std::is_same<decltype(Experiment::check(0, std::declval<U>()...)),
                              yes&>::value, int>::type = 0>
      Experiment(U &&...u):T{ std::forward<U>(u)... }
      {}
    };
    
    // TEST
    
    struct AbstractBase {
      protected:
        AbstractBase(int, float);
        virtual void f() = 0;
    };
    
    struct Annoyer { Annoyer(int); };
    
    void x(Experiment<AbstractBase>);
    void x(Annoyer);
    
    int main() {
      x({42});
      x({42, 43.f});
    }
    

    更新:该代码也适用于Clang。

    关于c++ - 检测(可能是抽象的)基类的 protected 构造方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12079711/

  • 10-17 00:30