从派生 类 引用基数 类 的更好习惯用法?

A better idiom for referring to base classes from derived classes?

假设我有一个

template <typename T>
class A : 
    class_with_long_name<T, and_many_other, template_arguments, oh_my_thats_long>,
    anotherclass_with_long_name<and_many_other, template_arguments_that, are_also_annoying, including_also, T> { ... }

现在,在 class A 的定义中,and/or 在其方法中,我需要引用两个 superclasses(例如访问 super[=28 中的成员=],或其中定义的类型等)但是,我想避免重复 superclass 名称。目前,我正在做的是:

template<typename T>
class A : 
    class_with_long_name<T, and_many_other, template_arguments, oh_my_thats_long>,
    anotherclass_with_long_name<and_many_other, template_arguments_that, are_also_annoying, including_also, T> 
{
    using parent1 = class_with_long_name<T, and_many_other, template_arguments, oh_my_thats_long>;
    using parent2 = anotherclass_with_long_name<and_many_other, template_arguments_that, are_also_annoying, including_also, T>;
    ...
 }

这显然有效,并将重复次数减少到 2 次;但如果可能的话,我宁愿避免这种重复。有没有合理的方法来做到这一点?

备注:

在A之前,你可以做

namespace detail
{
    template <typename T>
    using parentA1 = class_with_long_name<T,
                                          and_many_other,
                                          template_arguments,
                                          oh_my_thats_long>;
    template <typename T>
    using parentA2 = anotherclass_with_long_name<and_many_other,
                                                 template_arguments_that,
                                                 are_also_annoying,
                                                 including_also,
                                                 T>;
}

然后

template<typename T>
class A : detail::parentA1<T>, detail::parentA2<T>
{
};

我认为,最好的选择就是你已经在做的事情。然而,如果你觉得你绝对不能容忍这个,这里有一些有趣的代码(如果我在生产代码审查期间看到这样的东西,我会竭尽全力摆脱它)。

template<class... INHERIT_FROM> 
struct inherit_publicly : public INHERIT_FROM... {
    struct parent_types {
        template <int N, class ARG, class... ARGS> struct get {
            using type = typename get<N-1, ARGS...>::type;
        };
        template <class ARG, class... ARGS> struct get<0, ARG, ARGS...> {
            using type = ARG;
        };
    };

    template <int N> using parent = typename parent_types::template get<N, INHERIT_FROM...>::type;

};

// **example usage** 

struct X { static constexpr const char* const name = "X"; };
struct Y { static constexpr const char* const name = "Y"; };
struct Z { static constexpr const char* const name = "Z"; };


#include <iostream>

struct A : inherit_publicly<X, Y, Z> {
    void print_parents() {
        std::cout << "First parent type: " << parent<0>::name << "; second: " << parent<1>::name << "; third: " <<parent<2>::name<< "\n";
    }
};

int main() {
    A a;
    a.print_parents();
}

现场演示:http://coliru.stacked-crooked.com/a/37cacf70bed41463

基于@Jarod 的解决方案:内部细节子命名空间怎么样?

namespace detail { namespace A {
    template <typename T>
    using parent1 = class_with_long_name<T,
                                          and_many_other,
                                          template_arguments,
                                          oh_my_thats_long>;
    template <typename T>
    using parent2 = anotherclass_with_long_name<and_many_other,
                                                 template_arguments_that,
                                                 are_also_annoying,
                                                 including_also,
                                                 T>;
} // namespace A
} // namespace detail

然后

template<typename T>
class A : detail::A::parent1<T>, detail::A::parent2<T>
{
};

如果您为所有 类 使用相同的访问说明符继承,您可以使用这样的东西:

template <typename...S>
struct Bases : public S... {
    template <size_t I>
    using super = typename std::tuple_element<I, std::tuple<S...>>::type;
};

这将使您能够按照通过 super<index>.

从它们继承的顺序访问所有基 类

简短示例:

#include <iostream>
#include <tuple>


template <typename...S>
struct Bases : public S... {
    template <size_t I>
    using super = typename std::tuple_element<I, std::tuple<S...>>::type;
};


class Foo
{
public:
    virtual void f()
    {
        std::cout << "Foo";
    }
};

class Fii
{
public:
    virtual void f()
    {
        std::cout << "Fii";
    }
};

class Faa : private Bases<Foo, Fii>
{
public:
    virtual void f()
    {
        std::cout << "Faa";
        super<0>::f(); //Calls Foo::f()
        super<1>::f(); //Calls Fii::f()
        std::cout << std::endl;
    }
};



int main()
{
    Faa faa;
    faa.f(); //Print "FaaFooFii"
    return 0;
}

您可以只使用 A::class_with_long_nameA::anotherclass_with_long_name

template<typename T>
class A 
    : class_with_long_name<T, and_many_other, template_arguments, oh_my_thats_long>
    , anotherclass_with_long_name<and_many_other, template_arguments_that, are_also_annoying, including_also, T> 
{
    // If you still want the typedefs.
    using parent1 = typename A::class_with_long_name;
    using parent2 = typename A::anotherclass_with_long_name;

    // If you don't.
    void foo() { A::class_with_long_name::bar(); }
};