【问题标题】:I need something like "using Base::*;"我需要类似“使用 Base::*;”的东西
【发布时间】:2011-08-07 07:20:54
【问题描述】:

如果我的基类有一个函数func(int),而我的派生类有一个函数func(double),则派生的func(double) 隐藏base::func(int)。我可以使用using 将基本版本带入派生的重载列表中:

struct base
{
   void func(int);
};

struct derived : base
{
   using base::func;
   void func(double);
}

好的,太好了。但是如果我不确定base 是否有func() 怎么办?即因为我正在做模板元编程,我实际上并不确定base 是什么,但我想将它的功能提升到相同的水平——如果它们存在的话。即把上面的例子改成:

struct base_with
{
   void func(int);
};
struct base_without
{
};

template <typename Base>
struct derived : Base
{
   using Base::func;  // if Base has a func(), I want to bring it in

   void func(double);
}

derived<base_with> testwith; // compiles
derived<base_without> testwithout;  // fails :-(

我需要using_if,比如boost::enable_if。好像不太可能……

提前致谢。

【问题讨论】:

  • 你最终想做什么? derived&lt;XXX&gt; 是干什么用的?
  • 我正在构建可以选择实现某些功能的类,具体取决于它们的使用方式/位置。在某种程度上,这基本上只是重构 - 即不是编写类 XWithFeatureA, XWithFeatureB, XWithFeatureAandB, ... 这会变成许多样板类,我想要 X 其中 feature_traits 决定使用哪些功能。
  • 系统中的对象的功能是“允许侦听器”、“具有自定义设置器”等。我认为我无法(或被允许)将其描述得足以让您确信具有可选功能的系统实际上是有意义的。
  • 我很困惑,谁是托尼,谁是托尼?看起来像是一种轻度的身份障碍:)

标签: c++ metaprogramming


【解决方案1】:

由于您愿意将using 语句放入派生类中,我假设您事先知道可能有兴趣引入哪些成员。您可以使用boost::enable_if 执行此操作:

struct base_with
{
    void func(int) { cout << "func(int)" << endl; }
};

struct base_without { };

// Custom traits, by default assume func() isn't present
template <class T> struct has_func : public boost::false_type { };

template<> struct has_func<base_with> : public boost::true_type { };

// Again, if nothing else is known, assume absence of func(int)
template <typename Base, class UseFunc = void> struct derived : Base
{
    derived() { cout << "ctor: derived without" << endl; }
    void func(double) { cout << "func(double)" << endl; }
};

// Derived with func(int)
template <typename Base> struct derived<Base, typename boost::enable_if< has_func<Base> >::type> : Base
{
    using Base::func; 
    derived() { cout << "ctor: derived with" << endl; }
    void func(double) { cout << "func(double)" << endl; }
};

对不起所有的印刷声明。现在如果你尝试

derived<base_with> testwith; 
derived<base_without> testwithout;

testwith.func(10);
testwith.func(10.5);
testwithout.func(10);
testwithout.func(10.5);

你应该看到

ctor:派生于
ctor:派生而没有
函数(整数)
函数(双)
函数(双)
函数(双)

显然,如果您尝试测试多个功能,这将变得可怕。如果我在做这种混合风格的编程,我可能更愿意为不同的特性使用不同名称的函数,这样它们就不会相互隐藏——那么就只需要公共继承了。无论如何都是有趣的问题。

【讨论】:

    【解决方案2】:

    我想我需要做一些类似的事情

    struct dummy_func
    {
    private:
       struct dumb_type {};
    
    // interesting: does this need to be public?
    public:
       // use a type that no one can see, so func is never chosen by ADT
       // and vararg just for paranoia
       void func(dumb_type, dumb_type, dumb_type,...) { };
    };
    
    ...
    template <typename T>
    struct has_func
    {
       enum { value = /* insert metaprogramming magic that checks for T::func */ }
    };
    
    template <typename Base>
    struct derived : Base
    {
       using enable_if<has_func<Base>, Base, dummy_func>::type::func;
       ...
    };
    

    grrr。当然这不起作用,因为 dummy_func 不是derived 的基础。就我而言,我可能会在必要时让它派生出来。但仍然勉强令人满意。

    【讨论】:

    • 我猜这与using Base::* 不一样,但* - 如果可能的话,“使用本课程中的所有内容”也会给我我想要的。
    猜你喜欢
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    相关资源
    最近更新 更多