1

最小的工作示例:

#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;
}

这行得通。

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

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

4

2 回答 2

2

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

如果是后者,你可以让你的元组持有 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 和副本省略的组合)。

于 2013-12-16T15:38:07.803 回答
1

您可以使用统一初始化。遗憾的是,您无法定义默认值,参数将使用默认构造函数或 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
于 2019-12-12T09:46:20.897 回答