【问题标题】:Access a type in a variadic template by index通过索引访问可变参数模板中的类型
【发布时间】:2015-04-19 11:01:57
【问题描述】:

我想通过索引获取可变参数模板中的类型。索引被指定为模板参数。 我设法找到了一个有效的“黑客”,但我相信它不符合可变参数模板编程的精神。此外,它使用额外的内存。

这里有一些解释的代码:

template <typename... InputPortTypes>
class PipelineReceiver
{

protected:

    // This tuple is used for storing types only
    // Hence, I would like to get rid of it, but I am not sure how.
    std::tuple<
    std::function<std::unique_ptr<InputPortTypes> (int)>...
    > InputPortsTuple;

    // This vector is used for storing the actual objects
    // This is needed to be able to access/change its elements
    // during run time later on.
    // The vector is used for storage of function pointers (i.e. of type std::function)
    // that represent methods of another object upstream the pipeline.
    std::vector<boost::any> InputPortsVector;

public:

    PipelineReceiver()
        {
            // create an empty vector of the required size
            InputPortsVector.resize(sizeof...(InputPortTypes));
        }

    void connectPorts(int InputPortIndex, boost::any c_OutputPort)
        {
            // connect ports
            InputPortsVector[InputPortIndex] = c_OutputPort;
        }

     // this function needs to be modified to avoid using InputPortsTuple
    template<int N>
    void getInputPortValue(void)
        {
            std::cout <<
                *boost::any_cast<decltype(std::get<N>(this -> InputPortsTuple))>(
                    InputPortsVector[N]
                    )(0) <<
                std::endl;
        }

};

我想删除对象InputPortsTuple 并将其替换为某种形式的递归过程,以推断getInputPortValue 中的类型。

理想情况下,我希望N 成为动态参数而不是模板参数。但是,我不确定这是否可能。

【问题讨论】:

  • 您可以使用std::declval&lt;std::tuple&lt;std::function&lt;std::unique_ptr&lt;InputPortTypes&gt; (int)&gt;...&gt;&gt;() 而不是this-&gt;InputPortsTuple 轻松删除未使用的成员,除非我遗漏了什么。 (我知道这不是你真正想要的。这只是一个稍微不那么糟糕的选择。)
  • 但实际上,为什么不直接将元素存储在一个元组中呢?为什么首先使用向量?您仍然可以更改元组。
  • @hvd 感谢您的 cmets。您在第一条评论中提出的建议是我目前正在做的更好的选择,但是,正如您所指出的,仍然不完美。我将发表另一条评论来解释为什么我需要使用向量。
  • @hvd 关于你的第二条评论,我试图解释为什么我需要向量定义之前的评论中的向量(即'This (the vector ) 需要能够在稍后的运行时访问/更改其元素')。我将尝试改进评论以使其更清晰。感谢您指出这一点。
  • 是的,我读到了,但我没有看到:元组也允许更改其元素:std::get&lt;N&gt;(tuple) 返回一个左值引用,您可以毫无问题地分配给它。

标签: c++ c++11 variadic-templates decltype boost-any


【解决方案1】:

你可以简单地滥用std::tuple_element

typename std::tuple_element<N, std::tuple<InputPortTypes...>>::type

注意:如果你可以使用 C++14,

std::tuple_element_t<N, std::tuple<InputPortTypes...>>

是做同样事情的更好方法。不过,并非所有常见的编译器都知道它。

【讨论】:

  • std::tuple_element_t中不需要::type后缀。
  • @ligoore 谢谢。愚蠢的复制和粘贴错误。
  • @Wintermute 感谢您的回复。如果我理解正确,您建议将decltype(std::get&lt;N&gt;(this -&gt; InputPortsTuple)) 替换为预先声明的类型std::tuple_element&lt;N, std::tuple&lt;InputPortTypes...&gt;&gt;::type。不幸的是,这不起作用。我收到一个运行时错误failed conversion using boost::any_cast。通过 decltype(std::get(this -> InputPortsTuple)) 和 typename std::tuple_element&lt;N, std::tuple&lt;InputPortTypes...&gt;&gt;::type 声明的变量的 typeid 关联的名称也不同。
  • 答案中的代码将为您提供参数包的第 n 种类型InputPortTypes。如果我正确阅读了您的代码,那么您想将其包装在 std::function&lt;std::unique_ptr&lt;T&gt;(int)&gt; 中,所以最终您正在寻找 std::function&lt;std::unique_ptr&lt;typename std::tuple_element&lt;N, std::tuple&lt;InputPortTypes...&gt;&gt;::type&gt;(int)&gt;
  • @Wintermute 我必须道歉。我迷失在符号中,没有注意到您指定了 InputPortTypes 模板的类型。谢谢你的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-23
  • 1970-01-01
  • 2013-02-07
  • 1970-01-01
  • 2018-06-27
  • 2016-04-13
相关资源
最近更新 更多