仅初始化c++11元组的第一个参数

Initialize only first argument of c++11 tuple

本文关键字:第一个 参数 元组 初始化 c++11      更新时间:2023-10-16

最小工作示例:

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

这是有效的。

有没有一种更优雅的方法可以像我在评论中画的那样只初始化第一个成员?一个只使用参数来构造第一个元组成员而不初始化其他元组成员的元组

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

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

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

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