【问题标题】:Remove duplicate template typename entry when inheriting继承时删除重复的模板类型名条目
【发布时间】:2015-05-14 10:51:51
【问题描述】:

我有一个继承自的模板类(从现在开始作为父类引用)。

模板类初始化一个融合列表成员变量,其中包含子类中指定的类和构造函数。

template<typename... ITEM_TYPES>
using List = boost::fusion::list<ITEM_TYPES...>;

template<typename... CHILDREN_TYPES>
class ElementContainer 
{ 
protected:
    const List<CHILDREN_TYPES...> children;
public:
     ElementContainer(CHILDREN_TYPES&&... args) : children(forward<CHILDREN_TYPES>(args)...) {}
};

子类示例:

class XMLSignatureDocument : public ElementContainer<XMLDeclarationElement, SignatureXMLElement>
{
public:
    XMLSignatureDocument() :ElementContainer(
        XMLDeclarationElement("<?xml version=\"1.0\" encoding=\"utf-8\"?>"),
        SignatureXMLElement("<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"></signature>"
        )) {};
};

当我创建这样一个子类时,我必须在列表中指定类的类型两次:

曾经在“继承自”规范中:

class XMLSignatureDocument : public ElementContainer<XMLDeclarationElement, SignatureXMLElement>

以及当我指定各个类的构造函数参数时:

XMLSignatureDocument() :ElementContainer(
    XMLDeclarationElement("<?xml version=\"1.0\" encoding=\"utf-8\"?>"),
    SignatureXMLElement("<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"></signature>"
    )) {};

我只想指定一次 - 当我还指定构造函数参数时,如下所示:

class XMLSignatureDocument : public ElementContainer<...>
{
public:
    XMLSignatureDocument() :ElementContainer(
        XMLDeclarationElement("<?xml version=\"1.0\" encoding=\"utf-8\"?>"),
        SignatureXMLElement("<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"></signature>"
        )) {};
};

并且仍然在父类中创建列表的编译时间。

如果不可能,我不会 100% 锁定在这个设计中 - 如果其他设计有可能并且完成同样的事情,我想听听。

我正在使用 Visual Studio 2014 (v140)(c++14) 工具集进行编译和 boost 库。

【问题讨论】:

    标签: c++ templates boost c++14 template-meta-programming


    【解决方案1】:

    您可以做相反的事情:在类声明中指定类型,并为构造函数参数使用通用初始化语法(尽管它不适用于显式构造函数):

    class XMLSignatureDocument : public ElementContainer<XMLDeclarationElement, SignatureXMLElement>
    {
    public:
        XMLSignatureDocument() :ElementContainer(
            {"<?xml version=\"1.0\" encoding=\"utf-8\"?>"},
            {"<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"></signature>"}
            ) {};
    };
    

    【讨论】:

      【解决方案2】:

      您可以在 ElementContainer 构造函数中构造模板参数类型。这适用于 explicit 构造函数,但前提是它们采用单个参数。

      ElementContainer 构造函数更改为模板函数,将参数转发给 CHILDREN_TYPES 构造函数:

      template <typename... Args>
      ElementContainer(Args&&... args) 
          : children(CHILDREN_TYPES{std::forward<Args>(args)}...) {}
      

      然后你可以自己传递字符串:

      XMLSignatureDocument() :ElementContainer(
              "<?xml version=\"1.0\" encoding=\"utf-8\"?>",
              "<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"></signature>") {};
      

      【讨论】:

      • 能否构建一个涉及元组和索引序列的构造,允许将参数包传递给显式构造的父级?我没有看到它,因为我们需要一包索引和类型,并且这些需要解包,但我可能是错的。如果我们不直接继承(即有一个中间助手),我认为我们可以完成这个?
      • 您的意思是使用 ElementContainer(std::make_tuple("..."), std::make_tuple("...")) 或隐含地计算出这些元组的东西?
      • 我怎样才能声明成员变量children?如果类型不是类模板变量,则类型未知?能否提供一个完整的编译代码示例?
      • like this?template class FuzzElementContainer { protected: const fuzzList children; public: template FuzzElementContainer(CHILDREN_TYPES&&... args) : children(CHILDREN_TYPES{ std::forward(args) }...) {} 朋友 ostream& operator
      • @TartanLlama 是的:某种 emplace-magic,其中每个元组的内容用于构造每个元素。 ElementContainer( std::piecewise_construct{}, std::make_tuple(。我可以使用一个中间助手来执行此操作,该助手将元组(一次一个)转发到每个基类,但我不知道在直接继承时如何做到这一点。
      猜你喜欢
      • 2019-09-02
      • 2018-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-19
      • 1970-01-01
      相关资源
      最近更新 更多