首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >检测(可能是抽象的)基类的受保护构造函数

检测(可能是抽象的)基类的受保护构造函数
EN

Stack Overflow用户
提问于 2012-08-22 19:01:03
回答 1查看 673关注 0票数 15

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

代码语言:javascript
运行
复制
template <class T>
class Wrapper : public T {
    public:
    template <typename... As>
    Wrapper(As && ... as) : T { std::forward<As>(as)... } { }
    // ... nice additions to T ...
};

这很管用..。大多数时候都是。有时,使用Wrapper类(Es)的代码必须使用SFINAE来检测如何构造这样的Wrapper<T>。然而,存在以下问题:就过载解析而言,Wrapper<T>的构造函数将接受任何参数--但是如果不能使用这些参数构造T类型,编译就会失败(这不在SFINAE的范围之内)。

我试图使用enable_if有条件地启用构造函数模板的不同实例化。

代码语言:javascript
运行
复制
    template <typename... As, typename std::enable_if<std::is_constructible<T, As && ...>::value, int>::type = 0>
    Wrapper(As && ... as) // ...

只要:

  • T的适当构造函数是public
  • T不是抽象的

我的问题是:如何摆脱上述两个限制?

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

对于第二个问题,我完全不知道--它是我需要更多的东西,因为有时是Wrapper实现了T的抽象函数,使它成为一个完整的类型。

我想要一个解决办法:

  • 按照标准是正确的
  • 作品范围: gcc-4.6.*、gcc-4.7.*或clang-3.*

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-08-22 19:36:53

这似乎对我当地的GCC很有效(4.7,鲁本夫提供的)。GCC在ideone上打印了几个“实现的”编译器内部错误。

我不得不将Experiment类的“实现细节”公之于众,因为出于某些原因(闻起来像是一个bug),我的GCC版本抱怨它们是私有的,即使只有类本身使用它。

代码语言:javascript
运行
复制
#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。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12079711

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档