以下程序运行良好:
struct M; // forward declare so compiler will recognize this type
struct N;
template< typename J > struct B { template< typename U > void Func1(); };
template<> template<> void B< M >::Func1< M >() {}
template<> template<> void B< N >::Func1< N >() {}
template<> template<> void B< M >::Func1< N >() {} // illegal specialization for this app
template< typename J > struct C { template< typename U > void Func2(); };
template<> template<> void C< M >::Func2< M >() {}
template<> template<> void C< N >::Func2< N >() {}
template< typename G > struct H { G g; };
int main()
{
H< B< M > > hbm;
hbm.g.Func1< M >(); // ok
hbm.g.Func1< N >(); // compiles and runs, but uses a semantically illegal specialization for this app
H< B< N > > hbn;
hbn.g.Func1< N >(); // ok
H< C< M > > hcm;
hcm.g.Func2< M >(); // ok
H< C< N > > hcn;
hcn.g.Func2< N >(); // ok
return 0;
}
结构B和C必须在编译时明确声明,并且只允许那些对应用有意义的特化。
但是从上面的代码中可以看出,我的下游开发人员(有一天!)可能能够创建语义上没有意义的语法正确的模式。具体来说,app只知道如何使用类和函数类型相同的类型。其余的都是荒谬的。
这似乎是新的C ++ 17 +功能之一,例如SFINAE,Constraints或Concepts。虽然我正在阅读这些内容,但我还没有做出选择的判断。在Alternatives下的cppreference中,如果编译器有能力,他们建议使用Concepts而不是SFINAE(我使用VS2015)。
将typename J约束为typename U?
的好方法是什么?答案 0 :(得分:2)
您可以使用enable_if:
template< typename J > struct B {
template<typename U>
typename std::enable_if<std::is_same<U, J>::value, void>::type
Func1();
};
http://coliru.stacked-crooked.com/a/efb499cf654f0f25
对于概念(未在近期(?)未来的标准中),上述相同的解决方案如下所示。
http://melpon.org/wandbox/permlink/li4Uh5Q6ilpnlhcl
template <class T, class U> concept bool Same = std::is_same<T,U>::value;
template< typename J > struct B {
template< typename U >
requires Same<J, U>
void Func1();
};