如何将模板mixin作为参数?

时间:2016-08-12 08:46:09

标签: c++ templates mixins

考虑到C ++模板mixin结构,我如何编写一个带有特定组件的mixin的函数?在此示例中,如何将withAandB提供给worksWithA()

struct Base {};

template <class T>
struct HasA : T
{
    int A;
};

template <class T>
struct HasB : T
{
    int B;
};

void WorksWithA(HasA<Base> &p)
{
    p.A++;
}

void WorksWithAandB(HasA<HasB<Base> > &p)
{
    p.A++;
    p.B++;
}

int _tmain(int argc, _TCHAR *argv[])
{
    HasA<Base> withA;
    HasA<HasB<Base> > withAandB;

    WorksWithA(withA); // OK
    WorksWithAandB(withAandB); // OK
    WorksWithA(withAandB); // KO, no conversion available

    return 0;
}

即使抛开构造问题或mixin排序(HasA<HasB<Base>> vs HasB<HasA<Base>>),我也看不到编写此函数的好方法,除了使它成为模板之外。

我目前处于没有C ++ 11的环境中,但如果现代C ++为此提供解决方案,我会感兴趣。

非常感谢!

5 个答案:

答案 0 :(得分:2)

您可以使WorksWithA模板函数接受包含HasA的任何类:

template<typename T>
void WorksWithA(HasA<T> &p)
{
  p.A++;
}

在这种情况下,您的代码编译时没有错误。

答案 1 :(得分:2)

我认为你还必须制作你的功能模板吗?

template <class T>
void WorksWithA(HasA<T> &p)
{
    p.A++;
}

template <class T>
void WorksWithAandB(HasA<HasB<T> > &p)
{
    p.A++;
    p.B++;
}

由于HasA<HasB<Base>>无法转换为HasA<Base>

答案 2 :(得分:2)

正如其他人所指出的,这些功能可能更适合作为模板。但是,当您使用它时,您还可以删除一些代码重复:

template<class B> 
void WorksWithA(HasA<B> &p) 
{ 
    p.A++; 
} 

template<class B> 
void WorksWithB(HasA<B> &p) 
{ 
    p.B++;
}

template<class Has>
void WorksWithAandB(Has &p)
{
    WorksWithA(p);
    WorksWithB(p);
}

此处WorksWithAAndB调用其他类型。因此:

  1. 您正在重复使用该代码。
  2. 您正在重复使用编译器对传递给WorksWithAWorksWithB的类型类型的检查作为传递给WorksWithAAndB的类型。

答案 3 :(得分:1)

你必须使WorksWithA成为一个功能模板;没有其他办法。考虑一下:WorksWithA适用于任何具有HasA mixin的类型。这只能用模板表达。

答案 4 :(得分:1)

此外,在HasAHasB具有接口含义的情况下,请考虑使用继承来解决此问题:

struct HasA
{
  int A;
  virtual ~HasA() = default;
};

struct HasB
{
  int B;
  virtual ~HasB() = default;
};

struct HasAB : HasA, HasB
{
};

struct Base : HasAB
{};

void WorksWithA(HasA &p)
{
  p.A++;
}

void WorksWithAandB(HasAB &p)
{
  p.A++;
  p.B++;
}

在这里,您可以使用实现WorkWithA接口的任何类的对象调用WithA,使用任何实现WorksWithAandB接口的类的对象调用HasAB

PS:不幸的是,在这个示例中,如果没有WorksWithAandB的继承,则无法使用实现HasAHasB的类的对象调用HasAB,但这可能是使用模板和SFINAE解决。