如何将Wrapper
的模板参数限制为Wrapper<Any,
MyArray
<AnyT>>
优雅?
- 不要打破内容协助(Visual Studio(。
- 高可读性。不使用黑客方法。
由于某些原因,大多数解决方案都喜欢黑客。 - 通过使用C 语法规则,在第一行中使其很明显。(不只是绿色评论(
解决方案1(模板专业化,失败1(
template<class T> class MyArray{};
template<class T,class T2> class Wrapper;
template<class T,class T2> class Wrapper<T,MyArray<T2>>{
using Test=int;
};
class B{};
class C{};
int main() {
Wrapper<C,MyArray<B>> wrapper;
return 0;
}
此代码是从https://stackoverflow.com/a/43518221(@max66(修改的。
上下文线索/语法突出显示IDE会被混淆。
就我而言,它标记了一些正确类型的错误,例如: -
class ShowError : public Wrapper<B,MyArray<C>>{
Test n=0; //<-- unknown "Test" (intellisense)
};
解决方案2(某些hacky field/typedef,失败2(
template<class T> class MyArray{
public: using MyArrayT=T;
};
template<class T,class T2> class Wrapper{
public: using myT=typename T2::MyArrayT;
//^ assert at compile time
};
这个想法来自https://stackoverflow.com/a/43518295(@jarod42(
类声明没有提及MyArray
,它只是使用hacky(较低的(方式(MyArrayT
(来强制执行T2
是MyArray
。
解决方案3(基类,失败2(
class MyArrayBase{};
template<class T> class MyArray : public MyArrayBase{ };
template<class T,class T2> class Wrapper{
//check something around MyArrayBase *object = new T2();
// or "is_base_of"
};
该代码是从限制的C 模板参数变为一个仅接受某些类型的C 模板的参数。
它与解决方案2相同。
对于普通用户而言并不明显。
解决方案4(Snifae,失败1(
通过在模板类声明(Wrapper
(上添加 std::enable_if
,我可以得到一个工作hack。
不幸的是,内容协助讨厌它。
参考
这是我阅读的其他链接: -
- http://www.informit.com/articles/article.aspx?p=376878(模板模板参数(
- 限制模板函数,仅允许某些类型(与模板类型无关作为参数相关(
您可以编写自定义类型特征is_specialization
,如下:
template<class Type, template<class...> class Template>
struct is_specialization
: std::false_type {};
template<template<class...> class Template, class... TArgs>
struct is_specialization<Template<TArgs...>, Template>
: std::true_type {};
然后,您只需要static_assert
即is_specialization
对于给定的模板参数是正确的:
template<class T,class T2>
class Wrapper {
static_assert(is_specialization<T2, MyArray>::value, "T2 must be a specialization of MyArray");
};