通过CRTP和多重继承消除冗余 [英] Eliminate redundancy with CRTP and multiple inheritance

查看:69
本文介绍了通过CRTP和多重继承消除冗余的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是针对C ++ 03的,而不是针对C ++ 11的.

This question is for C++03, not C++11.

在某些情况下,我正在使用具有多重继承的CRTP,并且我很想知道是否有一种方法可以删除在指定以下B类型时创建的冗余.

I have a case where I am using CRTP with multiple inheritance, and I am curious to know if there is a way to remove the redundancy that is created when specifying the type of B below.

#include "boost/typeof/typeof.hpp"
#include "boost/units/detail/utility.hpp"
#include <iostream>
#include <string>

struct One{};
struct Two{};

template<typename T>
struct Type
{
   static std::string name(void)
   {
      return boost::units::detail::demangle(typeid(T).name());
   }
};

template<typename T1,
         typename T2>
struct A
{
   typedef A<T1, T2> Self;

   A()
   {
      std::cout << Type<Self>::name() << std::endl;
   }
};

template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, B<T1, T2, T3> >, // The B<T1, T2, T3> here is redundant
           public A<Two, B<T1, T2, T3> >
{
   typedef B<T1, T2, T3> Self;

   B()
   {
      std::cout << Type<Self>::name() << std::endl;
   }
};

int main(int argc, char* argv[])
{
   B<int, int, int> t;
   return 0;
}

Coliru

B的模板参数数量增加,模板参数本身很复杂以及BA继承多次时,问题变得更加严重.我想最小化B模板参数的重复.具体来说,我正在寻找一种在B或某些等效的this编译时版本的继承列表中访问typedef B<T1, T2, T3> Self的方法.

The problem worsens when the number of template parameters for B increases, when the template arguments themselves are complex, and when B inherits from A more times. I'd like to minimize the repetition of B's template parameters. Specifically, I am looking for a way to access the typedef B<T1, T2, T3> Self up in the inheritance list for B, or some equivalent compile-time version of this.

我不能:

  • 使用前向声明为B以上的B输入typedef,因为我无权访问模板参数
  • 在继承定义中添加typedef ,因为语法不允许这样做
  • 从类内部访问typedef,因为它尚不存在
  • Make a typedef for B above B using a forward declaration, because I don't have access to the template parameters
  • Make a typedef inside of the inheritance definition because the syntax doesn't allow that
  • Access the typedef from inside the class, because it doesn't exist yet

类似下面的内容(都不是有效的代码,但是会显示我想要的效果):

Something like the below (none of which are not valid code, but display the effect I am looking for):

template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, Self>, // Cannot access the typedef yet
           public A<Two, Self>
{
   typedef B<T1, T2, T3> Self;
};

template<typename T1,
         typename T2,
         typename T3>
struct B : typedef B<T1, T2, T3> Self, // Invalid syntax
           public A<One, Self>, 
           public A<Two, Self>
{

};

template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, B>, // I wish this would work
           public A<Two, B>
{

};

template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, BOOST_TYPEOF(*this)>, // lol
           public A<Two, BOOST_TYPEOF(*this)>
{

};

是否可以访问this的编译时版本?

Is there a way to access a compile-time version of this?

推荐答案

问题所在:

template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, B>, // I wish this would work
           public A<Two, B>
{

};

是您的template <typename T1, typename T2> struct A要求 被T2一个 type 实例化,而您希望做的是 用T2一个 template 实例化它,即 template<typename, typename,typename> struct B.

is that your template <typename T1, typename T2> struct A asks to be instantiated with T2 a type, whereas what you wish you could do is instantiate it with T2 a template, namely template<typename, typename,typename> struct B.

如果A的定义位于您自己的控件中,那么也许(尽管可能不是)一种解决方案 使A的定义与您的愿望保持一致:

If the definition of A lies in your own control, then perhaps - though perhaps not - a solution is to make the definition of A consistent with your wish:

#include "boost/typeof/typeof.hpp"
#include "boost/units/detail/utility.hpp"
#include <iostream>
#include <string>

struct One{};
struct Two{};

template<typename T>
struct Type
{
   static std::string name(void)
   {
      return boost::units::detail::demangle(typeid(T).name());
   }
};

template<typename T1,
         template<typename, typename, typename> class T2
>
struct A
{

   A()
   {
      std::cout << Type<A>::name() << std::endl;
   }
};


template<typename T1,
         typename T2,
         typename T3>
struct B : public A<One, B >,
           public A<Two, B >
{
   B()
   {
      std::cout << Type<B>::name() << std::endl;
   }
};


int main(int argc, char* argv[])
{
   B<int, int, int> t;
   return 0;
}

该程序打印:

A<One, B>
A<Two, B>
B<int, int, int>

此解决方案的价格限制了 A可以为实例化模板的对象提供CRTP基础,例如 B,恰好是三个typename参数.

The price of this solution is restricting the classes for which A can furnish a CRTP base to ones that instantiate a template, like B, of exactly three typename parameters.

也许您很幸运,这个限制不会阻止任何其他限制 希望你有.但是如果您还需要A来提供CRTP基础 对于实例化某些模板的类,这些模板不完全具有三个 typename参数,然后咬.

Perhaps you are lucky enough that this restriction does not thwart any other wishes you have. But if you also need A to furnish a CRTP base for classes that instantiate some template that does not have exactly three typename parameters, then it bites.

提供了您需要A为其提供CRTP的所有类 base是仅具有typename参数的模板的实例, 并且最多有N个,那么您仍然可以在其中使用C ++ 03解决方案 相同的精神:

Provided that all of the classes for which you need A to furnish a CRTP base are instantiations of templates that have only typename parameters, and have at most N of them, then you can still have a C++03 solution in the same spirit:

您根据架构定义A:

template<typename T1,
         template<typename /*1*/,.... typename /*N*/> class T2
>
struct A { ... };

对于以A为CRTP基础的每个模板Y,您需要提供 完全N参数,采用默认的填充"参数 void,如有必要.例如,如果N == 3:

And for each template Y for which A is to be a CRTP base, you provide exactly N parameters, employing "padding" parameters that default to void, as necessary. For example, if N == 3:

#include "boost/typeof/typeof.hpp"
#include "boost/units/detail/utility.hpp"
#include <iostream>
#include <string>

struct One{};
struct Two{};

template<typename T>
struct Type
{
   static std::string name(void)
   {
      return boost::units::detail::demangle(typeid(T).name());
   }
};

template<typename T1,
         template<typename, typename, typename> class T2
>
struct A
{

   A()
   {
      std::cout << Type<A>::name() << std::endl;
   }
};


template<typename T1, typename T2 = void, typename T3 = void>
struct B : public A<One, B >,
           public A<Two, B >
{
   B()
   {
      std::cout << Type<B>::name() << std::endl;
   }
};

template<typename T1, typename T2, typename T3 = void>
struct C : public A<One, C >,
           public A<Two, C >
{
   C()
   {
      std::cout << Type<C>::name() << std::endl;
   }
};

template<typename T1, typename T2, typename T3>
struct D : public A<One, D >,
           public A<Two, D >
{
   D()
   {
      std::cout << Type<D>::name() << std::endl;
   }
};



int main(int argc, char* argv[])
{
   B<int> b;
   C<int,int> c;
   D<int,int,int> d;
   return 0;
}

该程序打印:

A<One, B>
A<Two, B>
B<int, void, void>
A<One, C>
A<Two, C>
C<int, int, void>
A<One, D>
A<Two, D>
D<int, int, int>

是的,更一般的解决方案使您陷入另一种冗余"状态, 这些多余的默认模板参数的形式.但是你 可能会发现它不太讨厌.

True, the more general solution sticks you with a different kind of "redundancy", in the form of those superfluous defaulted template parameters. But you may find it a less irksome kind.

(gcc 5.1/clang 3.6,C ++ 03)

(gcc 5.1/clang 3.6, C++03)

这篇关于通过CRTP和多重继承消除冗余的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆