【问题标题】:Simple parameter pack expansion: expected ';'简单的参数包扩展:预期的 ';'
【发布时间】:2014-05-26 04:39:40
【问题描述】:

在下面的sn-p中:

void normalize(path& p)
{
   // do something with p
}

template<typename... T>
void normalize(T&... t)
{
     normalize(t)...;  // (L)
}

在我的实际理解中,(L) 行扩展为:

template<typename... T>
void normalize(T&... t)  // T = {t1, t2, t3}, for example
{
    normalize(t1), normalize(t2), normalize(t3);
}

这些表达式中的每一个都将执行normalize 的单参数版本。但是,g++ (4.8.1) 向我抛出以下错误:

prueba.cpp: In function 'void normalize(T& ...)':
prueba.cpp:155:17: error: expected ';' before '...' token
     normalize(t)...;
             ^
prueba.cpp:155:20: error: parameter packs not expanded with '...':
     normalize(t)...;
                    ^
prueba.cpp:155:20: note:         't'

我的代码有什么问题?

【问题讨论】:

标签: c++ templates c++11 variadic-templates g++4.8


【解决方案1】:

在此上下文中不允许扩展参数包。如果你创建了一个助手类pass,你可以执行以下操作:

pass{(normalize(std::forward<T>(t)), 0)...};

帮助类 pass 可能如下所示:

struct pass
{
    template <typename ...Args>
    explicit pass(Args&&...) { }
};

【讨论】:

  • 我不明白为什么需要 ", 0" 表达式
  • @Peregring-lk:normalize 的返回类型是void,但您不能将void 作为参数传递给函数/构造函数。出于这个原因,我使用逗号运算符来评估表达式,并获取虚拟值作为参数。
  • 在阅读您的评论之前我才意识到这一点。无论如何,感谢您证实了我的怀疑!
  • 对于{}initializer-clauses 会按照它们出现的顺序进行评估。不幸的是,高达 4.9 的 GCC 在这方面仍然存在问题。无论如何,我更喜欢{},因为它避免了最棘手的解析问题
  • 你也可以试试:[](...){}(normalize(std::forward&lt;T&gt;(t)), 0)...);。带有未指定参数的匿名 lambda [](...){} 似乎能够在不定义 pass 的情况下提供必要的扩展上下文。
【解决方案2】:

我认为您可能希望将参数包解压缩到函数调用站点或元组中,如下所示:

  make_tuple(normalize(t)...);  // (L)

例如,以下代码将在 gcc-4.8.1 下编译:

#include <tuple>
using namespace std;
typedef  int path;
void normalize(path& p)
{
   // do something with p
}

template<typename... T>
void normalize(T&... t)
{
  auto tp = make_tuple(normalize(t)...);  // (L)
  //do whatever you want with the components of tp ...
}

main() {}

【讨论】:

  • 是的,它是一种旧的 c/c++ 语法,仍然可以使用 g++ 4.8.1 进行编译。不想要噪音,所以使用最低限度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多