Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么';t原始卷曲构造函数{}是否返回右值?_C++_Templates_C++17_Variadic Templates_Generic Lambda - Fatal编程技术网

C++ 为什么';t原始卷曲构造函数{}是否返回右值?

C++ 为什么';t原始卷曲构造函数{}是否返回右值?,c++,templates,c++17,variadic-templates,generic-lambda,C++,Templates,C++17,Variadic Templates,Generic Lambda,假设您有一个带有std::tuple的变量类,它可以用args+1个新的arg移动构造。当使用std::apply()和原始花括号构造函数构造时,该构造函数不会返回右值。这意味着该类不是移动构造的。下面举一个例子来说明 #include <cstdio> #include <tuple> #include <type_traits> #include <unordered_map> #include <vector> template

假设您有一个带有
std::tuple
的变量类,它可以用args+1个新的arg移动构造。当使用
std::apply()
和原始花括号构造函数构造时,该构造函数不会返回右值。这意味着该类不是移动构造的。下面举一个例子来说明

#include <cstdio>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <vector>

template <class... Args>
struct icecream {
    icecream() = default;

    template <class... MoreArgs>
    icecream(icecream<MoreArgs...>&& ice) {
        std::apply(
                [this](auto&&... ds) {
                    data = { std::move(ds)..., {} };
                },
                std::move(ice.data));
    }

    // This works :

    // template <class... MoreArgs>
    // icecream(icecream<MoreArgs...>&& ice) {
    //  std::apply(
    //          [this](auto&&... ds) {
    //              data = { std::move(ds)...,
    //                  std::move(std::vector<double>{}) };
    //          },
    //          std::move(ice.data));
    // }

    std::tuple<std::vector<Args>...> data{};
};

int main(int, char**) {
    icecream<int> miam;
    std::get<0>(miam.data).push_back(1);
    std::get<0>(miam.data).push_back(2);

    icecream<int, double> cherry_garcia{ std::move(miam) };

    printf("miam : \n");
    for (const auto& x : std::get<0>(miam.data)) {
        printf("%d\n", x);
    }

    printf("\ncherry_garcia : \n");
    for (const auto& x : std::get<0>(cherry_garcia.data)) {
        printf("%d\n", x);
    }

    return 0;
}
这个例子有点简单,但说明了这一点。在第一个move构造函数中,使用
{}
并构造元组副本。如果使用硬编码的
std::move()
取消对第二个构造函数的注释,则它可以工作

我测试VS-latest、clanglatest和gcc-latest。都有相同的结果。(魔杖盒:)

所以问题是,为什么不返回一个右值呢?很明显,我在curly构造函数中遗漏了一些东西。这可能与变量无关,但我想我最好展示一下真实的场景

为什么原始卷曲构造函数{}不返回右值

问题是另一个

问题是

data = { std::move(ds)..., {} };
调用“直接构造函数”(中的构造函数(2))

不是“转换构造函数”(构造函数(3))

或者也

data = { std::move(ds)..., std::vector<double>{} };

您期望得到什么样的输出,而您没有得到?&&在模板的参数中,它不是右值引用,而是“通用引用”。你的意思是把构造函数作为模板吗?答案太棒了!非常感谢。在这个特殊的情况下,我不希望完美的转发,因为这确实是一个只移动的设计。我没有想到对构造类的成员使用tuple_元素。这将非常有效。又是thx
constexpr tuple( const Types&... args );       (2)
template< class... UTypes >
constexpr tuple( UTypes&&... args );           (3)
data = { std::move(ds)..., std::move(std::vector<double>{}) };
data = { std::move(ds)..., std::vector<double>{} };
template <typename ... MoreArgs,
   std::enable_if_t<sizeof...(MoreArgs)+1u == sizeof...(Args)> * = nullptr>
icecream(icecream<MoreArgs...>&& ice) {
    std::apply(
            [this](auto && ... ds) {
                data = { std::forward<decltype(ds)>(ds)..., 
                         std::tuple_element_t<sizeof...(Args)-1u,
                                              decltype(data)>{} };
            },
            std::move(ice.data));
}