2016-04-29 48 views
3

我有一种情况,我想定义一个专门化为相同的另一个类的实例化。这里是什么,我希望有一个简单的例子(在这个例子中一个完整的intantiation;在我实际的问题,我希望有一个偏特):定义一个专业化作为另一个类的实例化

//Template class 
template <int i> class Foo { /*...*/ }; 

//Another, completely different, template class 
template <int i,int j> class Bar { /*...*/ }; 

//Ordinary specialization of Foo 
template <> class Foo<0> { /*...*/ }; 

//Bogus specializations of Foo that 
// hopefully explain what I want. 
template <> class Foo<1> = Bar<1, 11>; 
template <> class Foo<2> = Bar<2, 42>; 
template <> class Foo<3> = Bar<3,-71>; 
... 

什么是这样做的好处? Foo<1>Foo<2>等的定义相当复杂,但很容易一次写成模板。有很多这样的定义。将Bar定义为Foo不是一种选择。只有一些值可以是专门的,并且Bar的专业化必须是手工选择的(因此int j的随机数)。

我通常会通过使用CRTP来达到这个效果。我会做一些很讨厌的修改Bar,然后像做:

template <> class Foo<1> : public Bar<1, 11,Foo<1>> {}; 
template <> class Foo<2> : public Bar<2, 42,Foo<2>> {}; 
template <> class Foo<3> : public Bar<3,-71,Foo<3>> {}; 
... 

显然,Bar将需要改变,有可能有些using声明拉下来的构造。这将是混乱。

我的问题:我能做得比这更好吗?也就是说,专业化可以定义为另一个模板类的实例吗?


注:优选的标准是C++ 14,尽管以后的版本是可接受的。

+0

'Foo'或'Bar'类型应该有彼此的任何知识吗?也就是说,CRTP将允许“Bar”“知道”关于“Foo”和“Foo”“知道”关于“Bar”,因为它继承了它(在你的例子中)。但是你想要一个基本的'typedef',这样任何和所有对'Foo <1>'的引用就好像有人写了'Bar <1, 11>',对吗? – txtechhelp

+0

@txtechhelp漂亮。我想过调用这个关于typedefs的问题,但typedefs并不适用于专业化.¶我正在写'Bar',所以'Bar'可以知道'Foo'。然而,'Foo'的基本定义不应该知道'Bar' - 只有它的专业化,我也定义了它。 – imallett

+0

查看[this]的答案(http://stackoverflow.com/questions/20419869/is-it-possible-to-define-an-implementation-template-specialization-as-typedef-of)question .. might必须添加一点额外的东西,但它可能会让你更接近? – txtechhelp

回答

1

会间接帮助吗? :)

template<int i> struct Indirection { using type = Foo<i>; }; 

template <> class Indirection<1> { using type = Bar<1, 11>; }; 
template <> class Indirection<2> { using type = Bar<2, 42>; }; 
template <> class Indirection<3> { using type = Bar<3, -71>; }; 

template<int i> 
using ActualFoo = typename Indirection<i>::type; 
+0

间接解决了所有问题,除了太多的间接问题。 – Yakk

+1

请注意,这使得'ActualFoo '上的模板参数不可能被扣除。 –

0

您可以使用继承而不是CRTP。

template <int i> struct Foo {}; 

template <int i,int j> struct Bar { Bar() {} }; 

template <> struct Foo<0> {}; 

template <> struct Foo<1> : public Bar<1, 11> { using Bar::Bar; }; 
template <> struct Foo<2> : public Bar<2, 42> { using Bar::Bar; }; 
template <> struct Foo<3> : public Bar<3,-71> { using Bar::Bar; }; 
+0

这实际上就是我上面写的,但没有CRTP。¶CRTP的原因是,例如, '酒吧<1,11>'有方法,应该像'Foo <1>'。例如,'Bar'可以定义'静态栏getBarPlusBar(Bar,Bar);'。使用CRTP这成为'静态FooType getBarPlusBar(FooType,FooType);',这意味着我现在可以去'Foo <1> foo3 = Foo <1> :: getBarPlusBar(foo1,foo2);' – imallett

+0

@imallett,你有两种选择。选择满足您最佳需求的产品。 –