C++0x:如何在没有引用的情况下获取可变模板参数?

4

假设有以下编造(而且确实很糟糕)的例子:

template<typename... Args>
void something(Args... args)
{
    std::tuple<Args...> tuple; // not initializing for sake of example
    std::get<0>(tuple) = 5;
}

如果你这样调用它,它就能工作:

int x = 10;
something<int>(x);

然而,如果你像这样调用它,它是不起作用的:
int x = 10;
something<int&>(x);

由于分配给5。假设无论出于什么原因,当定义元组时无法初始化元组,那么在指定类型为引用时,如何使其正常工作?
具体来说,即使Args...是int&,我也希望元组为std::tuple。
实际用例涉及将字符串反序列化为元组,其中Args...是传递给函数的参数类型,然后通过展开元组调用该函数。除了函数通过引用接受参数时,一切都很好。
我正在使用gcc 4.5.2,但会接受尚未在此编译器中实现的答案。
2个回答

12

我不理解你的问题。这段代码在GCC下工作良好,我看不出为什么它不能工作。

#include <tuple>

template<typename... Args>
void something(Args... args)
{
  std::tuple<Args...> tuple{args...};
  std::get<0>(tuple) = 5;
}

int main() {
  int x = 10;
  something<int&>(x);
}

[js@HOST2 cpp]$ g++ -std=c++0x main1.cpp
[js@HOST2 cpp]$

我不知道你所说的“初始化模板”是什么意思。


既然你现在更新了问题,我也可以更新我的回答。

template<typename... Args>
void something(Args... args)
{
  std::tuple<typename std::decay<Args>::type...> tuple;
  std::get<0>(tuple) = 5;
}

decay 移除 const / volatile ,移除引用并将数组和函数类型转换为相应的元素和函数指针。这似乎是您要寻找的内容。


抱歉,我想说的是,“如果我无法初始化元组”,也就是说,无法包含你示例中的 {args...}。 - Sydius
1
@Sydius 如果你不想传递引用类型,那么你必须初始化一个引用。如果你没有初始化引用,你会期望get<0>(tuple) = 5赋值给什么呢? - Johannes Schaub - litb
我对我的问题进行了澄清。即使模板是引用类型,我也不希望元组成为引用。实际用例要复杂得多;这只是一个虚构的示例,以说明问题。 - Sydius
@Sydius,我认为你应该描述一下更为复杂的使用情况(不是它的代码,只是它的场景)。所有这些都只是在解决真正问题和解决方案之间的涉足。我提出的解决方案可能只是解决这个简化的测试用例的方法,可能并不是你更复杂的使用情况的真正解决方案。 - Johannes Schaub - litb
听起来正是我想要的,但在gcc 4.5.2中,我得到了“expected a type, got ‘std::decay<Args>::type ...’”的错误提示。 - Sydius
我添加了实际使用情况(简要),但我相信,如果我能让我的简化案例工作,我就能解决我的问题。我认为std::decay听起来正是我想要的,如果我能让它编译通过的话。也许在gcc 4.5.2中它在这个上下文中并没有得到完全支持? - Sydius

5

您尝试过使用std::tuple<std::remove_reference<Args>...>吗?


我觉得我可能做错了,但是当我尝试那样做时,我得到了以下错误:error: no match for ‘operator=’ in ‘std::get [with long unsigned int __i = 0ul, _Elements = {std::remove_reference<int&>}, typename std::__add_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type = std::remove_reference<int&>&](((std::tuple<std::remove_reference<int&> >&)(& tuple))) = 5’ - Sydius
当您使用元函数时,除非您实际上想将元函数用作类型本身,否则必须访问其返回类型。我在我的帖子中忘记了这一点。我认为语法应该是 std::remove_reference<Args>::type ... - Edward Strange

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接