如何优雅地将模板参数限制为"<AnyT><Certain_Class>"?



如何将Wrapper的模板参数限制为Wrapper<Any, MyArray <AnyT>>优雅?

  1. 不要打破内容协助(Visual Studio(。
  2. 高可读性。不使用黑客方法。
    由于某些原因,大多数解决方案都喜欢黑客。
  3. 通过使用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(来强制执行T2MyArray

解决方案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_assertis_specialization对于给定的模板参数是正确的:

template<class T,class T2>
class Wrapper {
    static_assert(is_specialization<T2, MyArray>::value, "T2 must be a specialization of MyArray");
};

相关内容

  • 没有找到相关文章

最新更新