【问题标题】:Initialize only first argument of c++11 tuple仅初始化 c++11 元组的第一个参数
【发布时间】:2013-12-16 15:32:00
【问题描述】:

最小的工作示例:

#include <tuple>

struct example
{
    example(int, char) {}
};

int main()
{
    std::tuple<example, int, double>
        my_tuple(example(0, 'x'), 42, .0);
    // std::tuple t = make_my_tuple(0, 'x');
    return 0;
}

这行得通。

有没有更优雅的方法来只初始化第一个成员,就像我在评论中所描绘的那样? 只接受参数来构造第一个元组成员而不初始化其他成员

我问的原因是什么?我只是对语言的语义感兴趣。

【问题讨论】:

  • 元组怎么知道第二个参数是42?
  • @itwasntpete 我还不想初始化第二个和第三个参数。
  • 好的,但是第一个参数应该是示例吗?
  • 你可以假设它现在总是struct example类型,是的。
  • 你是说你想要为元组的所有成员除了第一个成员执行完全-indeterminate值?如果是这样,我不知道您将如何使用元组来做到这一点(无论如何,不​​用自己制作)。至少 std::tuple 将对未指定的成员进行值初始化,并且我看不到您将采取任何方式(至少不是很明显),并不是说我可以理解您想要的原因。

标签: c++ c++11 stdtuple


【解决方案1】:

你说给其他两个成员赋值是没有必要的——你担心表现吗?或者这些成员可能没有合适的价值?

如果是后者,你可以让你的元组持有 boost::optionals。例如

#include <tuple>
#include <boost/optional.hpp>

using namespace boost;

struct example
{
    example(int, char) {}
};

typedef std::tuple<example, optional<int>, optional<double>> MyTuple;

int main()
{
   MyTuple my_tuple(example(0, 'x'), optional<int>(), optional<double>());
   return 0;
}

您现在在语义上拥有“未初始化”的 int 和 float,并且可以查询它们的值。

为了使其更优雅,您可以将其包装到一个函数中,使用完美的参数转发习惯用法(通常;在这种情况下,您的参数复制起来很便宜,因此这样做不会提高速度):

template <class... Args>
MyTuple make_mytuple(Args&&... args)
{
    return MyTuple(example(std::forward<Args>(args)...), optional<int>(), optional<double));
}

这个模板的优点是它对示例构造函数的变化具有弹性。如果您添加另一个参数,只需使用新参数调用 make_mytuple 即可。

您关于元组构造中复制的另一点是有效的,但实际上我相信这对大多数编译器来说都是最佳的。 (将右值按值传递给函数时,RVO 和副本省略的组合)。

【讨论】:

  • 谢谢,但我不担心找到好的起始值。我只是希望构造函数可以更“舒适”地调用。
  • 好的,谢谢,尽管它仍然对第 2 和第 3 个成员进行了不必要的初始化。但至少,它有助于提出问题。 :)
  • 确实如此,但如果是可选的,默认初始化成本与初始化布尔值相同,因此如果您要使用比 int 或 double 初始化成本更高的类型,它会很快。此外,它还为您提供了询问“此元素是否已初始化?”的语义
【解决方案2】:

您可以使用统一初始化。遗憾的是,您不能定义默认值,参数将使用默认构造函数或 0 进行初始化。

#include <iostream>
#include <tuple>

enum class Result {Full, Partial, Empty};
std::tuple<bool, int, double> get_tuple(Result type)
{
    if (type == Result::Full)
        return {true, 42, 3.14159};
    else if (type == Result::Partial)
        return {true, 42, {}};
    else
        return {};
}

int main()
{
    bool b;
    int i;
    double d;

    std::tie(b, i, d) = get_tuple(Result::Full);
    std::cout << b << " " << i << " " << d << std::endl;

    std::tie(b, i, d) = get_tuple(Result::Partial);
    std::cout << b << " " << i << " " << d << std::endl;

    std::tie(b, i, d) = get_tuple(Result::Empty);
    std::cout << b << " " << i << " " << d << std::endl;

    return 0;
}

输出:

1 42 3.14159
1 42 0
0 0 0

【讨论】:

    猜你喜欢
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 2018-10-11
    • 2020-08-26
    • 2013-10-19
    • 1970-01-01
    相关资源
    最近更新 更多