考虑到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 ++为此提供解决方案,我会感兴趣。
非常感谢!
答案 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
调用其他类型。因此:
WorksWithA
和WorksWithB
的类型类型的检查作为传递给WorksWithAAndB
的类型。答案 3 :(得分:1)
你必须使WorksWithA
成为一个功能模板;没有其他办法。考虑一下:WorksWithA
适用于任何具有HasA
mixin的类型。这只能用模板表达。
答案 4 :(得分:1)
此外,在HasA
和HasB
具有接口含义的情况下,请考虑使用继承来解决此问题:
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
的继承,则无法使用实现HasA
和HasB
的类的对象调用HasAB
,但这可能是使用模板和SFINAE解决。