标签: stdtuple

为什么make_tuple的实现不会通过大括号初始化返回?

要理解这个问题,请先阅读此答案.

我检查了不同的历史make_tuple实现(包括2012年的clang版本).在C++ 17之前我会期望它们,return {list of values ... }但它们都会在返回之前构造元组.它们都是非常简化的当前cppreference示例:

template <class... Types>
auto make_tuple(Types&&... args)
{
    return std::tuple<special_decay_t<Types>...>(std::forward<Types>(args)...);
}
Run Code Online (Sandbox Code Playgroud)

它没错,但返回大括号初始化的重点是直接构造返回的对象.在C++ 17之前,没有保证的复制省略甚至在概念上消除了临时性.但即使使用C++ 17,我也不一定会期望花括号在这个例子中消失.

为什么在任何C++ 11/14实现中都没有花括号?换句话说,为什么不呢

 template <class... Types>
    std::tuple<special_decay_t<Types>...> make_tuple(Types&&... args)
    {
        return {std::forward<Types>(args)...};
    }
Run Code Online (Sandbox Code Playgroud)

c++ c++11 stdtuple list-initialization c++17

1
推荐指数
1
解决办法
229
查看次数

我无法在使用forward_as_tuple创建的元组中按类型访问元素

我正在使用C++ 17和Visual C++ 2017,我正在创建一个std::tuple引用std::forward_as_tuple.

从C++ 14开始,可以通过使用类类型而不是索引来访问元组的元素.

当我尝试下面的代码时,我有编译错误

 error C2338: duplicate type T in get<T>(tuple)
Run Code Online (Sandbox Code Playgroud)

你知道如何访问以这种方式创建的元组中的元素吗?

下面是示例代码

struct CA { 
    int data_ = 0; 
};

struct CB { 
    int data_ = 0; 
};

int main()
{
    CA a;
    CA b;

    auto joined_objects = std::forward_as_tuple(a, b);  

    std::cout << std::get<0>(joined_objects).data_ << std::endl; // works
    std::cout << std::get<CA &>(joined_objects).data_ << std::endl; // fails
 }
Run Code Online (Sandbox Code Playgroud)

c++ perfect-forwarding stdtuple c++17

1
推荐指数
1
解决办法
53
查看次数

c ++将模板化函数应用于元组的每个元素

template<typename T>
void print(T& t)
{
    std::cout << t << std::endl;
}

template<typename ... Args>
class Container 
{

    public:

    Container(Args&& ... args)
    : values_(std::forward<Args>(args)...)
    {}

    template<int INDEX>
    typename std::tuple_element<INDEX, std::tuple<Args...> >::type& get()
    {
        return std::get<INDEX>(values_);
    }

    void display()
    {
        // (obviously) does not compile !
        std::apply(print,values_);
    }

    private:
    std::tuple<Args ...> values_;

};
Run Code Online (Sandbox Code Playgroud)

上面的代码显示了意图但不正确(注释的地方),因为函数“print”需要一个模板。

有没有办法将(适当模板化的)打印函数调用到元组 values_ 的每个元素?

运行代码:https : //onlinegdb.com/SJ78rEibD

c++ templates apply variadic-templates stdtuple

1
推荐指数
1
解决办法
46
查看次数

为什么 `std::make_tuple` 需要移动语义?

std::tuple我认为通过std::make_tuplerequire 右值引用参数( type )创建一个非常有意识的设计决策T&&

然而,这意味着对象类型的移动语义 ( std::move 只不过是 to 的强制转换T&&,而且我对构建始终需要这样做的对象感到不太舒服std::tuple

int x = 7, y = 5;
std::tuple<int, int> fraction = make_tuple<int, int>( x, y ); // fails
Run Code Online (Sandbox Code Playgroud)

关于上述内容,编译器说:

错误 C2664: 'std::tuple<int,int> std::make_tuple<int,int>(int &&,int &&)': 无法将参数 1 从 'int' 转换为 'int &&'

message : 您无法将左值绑定到右值引用

std::tuple如果您不使用,则可以从左值制作 a没有问题make_tuple

std::tuple<int, int> fraction = { x, y }; // ok
Run Code Online (Sandbox Code Playgroud)

我的问题是,这是为什么?

c++ stdtuple

1
推荐指数
1
解决办法
871
查看次数

std :: tuple_element需要深度模板即时功能

在这里http://en.cppreference.com/w/cpp/utility/tuple/tuple_element给出了std :: tuple_element的可能实现.

 template< std::size_t I, class T >
struct tuple_element;

// recursive case
template< std::size_t I, class Head, class... Tail >
struct tuple_element<I, std::tuple<Head, Tail...>>
    : std::tuple_element<I-1, std::tuple<Tail...>> { };

// base case
template< class Head, class... Tail >
struct tuple_element<0, std::tuple<Head, Tail...>> {
   typedef Head type;
};
Run Code Online (Sandbox Code Playgroud)

但是,如果元组有很多参数(超过100或200个参数),这个实现需要深度递归实例化.

Q1:为什么C++ 11没有添加特殊运算符来获取索引元素?像元组[2]或元组[0]?

Q2:有可能减少深度实例化吗?例如,在D语言中,更多模板算法(在typetuple中)需要O(log(N))深度实例化.

编辑:Q1:为什么C++ 11没有添加特殊运算符来从变量模板获取索引元素?like template <class ... T> struct index {typedef T [3] third_element;}

c++11 stdtuple

0
推荐指数
2
解决办法
1240
查看次数

用法c ++ 11 std :: tuple在大项目中

C++ 11添加了非常有用的容器std :: tuple,现在我可以将许多结构转换为std :: tuple:

// my Field class
struct Field 
{
     std::string path;
     std::string name;
     int id;
     int parent_id;
     int remote_id;    
};

//create
Field field = {"C:/", "file.txt", 23, 20, 41 };  

 //usage
  foo( field.path );
  field.name= new_name;
  int id = field.id;
Run Code Online (Sandbox Code Playgroud)

//to std::tuple,               /--path,  /--name      /--id, /--parend_id,   /--remote_id
using Field = std::tuple< std::string, std::string , int,   int ,           int >;

//create
auto field = make_tuple<Field>("C:\", "file.txt", 23, 20, 41);      



// usage
     foo( std::get<0>(field) );  // may …
Run Code Online (Sandbox Code Playgroud)

c++ tuples c++11 stdtuple

0
推荐指数
1
解决办法
657
查看次数

是否有可能避免重复元组上的std :: move()?

假设我有一个元组和一个函数:

typedef std::tuple< std::unqiue_ptr<int>, std::unqiue_ptr<char> > SomeTuple;          
void someFunction( std::unqiue_ptr<int>, std::unqiue_ptr<char> );
Run Code Online (Sandbox Code Playgroud)

所以在辅助函数中我将元组展开为参数:

void unroll( SomeTuple &t )
{
    someFunction( std::get<0>( std::move( t ) ), std::get<1>( std::move( t ) ) );
}
Run Code Online (Sandbox Code Playgroud)

它有效,但我想避免重复std::move多次.天真的解决方案如:

void unroll( SomeTuple &t )
{
    auto &&rt = std::move( t );
    someFunction( std::get<0>( rt ), std::get<1>( rt ) );
}
Run Code Online (Sandbox Code Playgroud)

显然不起作用,因为rt是一个lvalue.那么有没有办法避免std::move()每次重复多次std::get

c++ rvalue-reference move-semantics c++11 stdtuple

0
推荐指数
1
解决办法
193
查看次数

在API设计中,我应该何时更喜欢长度为2 std :: tuple?

我正在写一个小型库,它有一些API函数返回两个东西(不同类型).我宁愿不为此声明一个结构; 所以我想回来一个std::pair<foo, bat>.但是 - 也许在这些现代时代我宁愿回来std::tuple<foo, bar>呢?

更一般地说,什么时候应该优先选择元组,何时配对更合适的构造?

c++ idiomatic c++11 stdtuple std-pair

0
推荐指数
1
解决办法
260
查看次数

std :: tuple成员成员比较失败

我想测试这个非常有趣的答案,并提出了这个最小的实现:

class A
{
    enum M { a };
    std::tuple<int> members;

public:

    A() { std::get<M::a>(members) = 0; }
    A(int value) { std::get<M::a>(members) = value; }
    A(const A & other) { members = other.members; }

    int get() const { return std::get<M::a>(members); }

    bool operator==(A & other) { return members == other.members; }
};
Run Code Online (Sandbox Code Playgroud)

一个简单的测试:

int main() {

    A x(42);
    A y(x);

    std::cout << (x==y) << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

一切都很好,直到我定义一个简单的struct B {};并尝试添加它的一个实例作为成员.我一写

std::tuple<int, B> members;
Run Code Online (Sandbox Code Playgroud)

operator== …

c++ stdtuple

0
推荐指数
1
解决办法
120
查看次数

如何从参数包构造引用的std :: tuple?

我有一个构建器类,我想将参数存储为引用,以便在后续构建中使用。

我想将可变数量的参数传递给我的类,使用类模板参数推导来推断模板参数,并将这些传递的参数作为引用存储在std :: tuple中。

从参数包转换为引用的std :: tuple的最简单方法是什么?

我发现std :: forward_as_tuple的功能与我想要的类似,但是我不想要转发引用,而且它在成员元组的初始化期间提供了语法错误。

template <typename... Ts>
struct Builder
{
using ArgsT = decltype(std::forward_as_tuple(Ts{}...));

ArgsT args_;

Builder(Ts&... ts) : args_(ts...) {}
};

int main()
{
    struct Foo
    {
        int a;
        double b;
    };

    Foo foo{};
    Builder fooBuilder{foo.a, foo.b};
}
Run Code Online (Sandbox Code Playgroud)

语法错误是:

错误:没有匹配的调用函数 std::tuple<int&&, double&&>::tuple(int&, double&)

c++ variadic-templates stdtuple c++17

0
推荐指数
1
解决办法
85
查看次数