假设我有一个
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> { ... }
现在,在A类的定义和/或其方法中,我需要引用两个超类(例如,访问超类中的成员,或者在其中定义的类型等)。但是,我想要避免重复超类名称。目前,我所做的是:
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;但如果可能的话,我宁愿避免这种重复。有合理的方法吗?
注意:
答案 0 :(得分:6)
在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>
{
};
答案 1 :(得分:1)
我认为,最好的选择就是你已经在做的事情。然而,如果你觉得你绝对不能容忍这一点,这里有一些有趣的代码(如果我在生产代码审查期间会看到这样的东西,我会煞费苦心地去除它)。
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();
}
答案 2 :(得分:1)
如果您使用相同的访问说明符继承所有类,则可以使用以下内容:
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;
}
答案 3 :(得分:1)
您可以使用A::class_with_long_name
或A::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(); }
};
答案 4 :(得分:0)
基于@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>
{
};