C++ 参数包和移动语义

C++ 参数包和移动语义,c++,c++17,variadic-templates,perfect-forwarding,C++,C++17,Variadic Templates,Perfect Forwarding,在下面的代码中,尝试通过参数包移动构造失败 我缺少什么,如何修复代码以运行所有4个变体 #include <utility> struct File { File(const char *filename) {} }; template<typename T> struct InflateInput { template<typename ...Args> InflateInput(int header, Args ...args)

在下面的代码中,尝试通过参数包移动构造失败

我缺少什么,如何修复代码以运行所有4个变体

#include <utility>

struct File
{
    File(const char *filename) {}
};

template<typename T>
struct InflateInput
{
    template<typename ...Args>
    InflateInput(int header, Args ...args) : source(args...) {}
    T source;
};

template<typename T>
struct DeflateInput
{
    template<typename ...Args>
    DeflateInput(int level, int header, Args ...args) : source(args...) {}
    DeflateInput(T &&stream, int level, int header) : source(std::move(stream)) {}
    T source;
};

int main()
{
    // case 1: ok
    File file{"filename"};
    DeflateInput deflate1(std::move(file), 5, 0);
    // case 2: ok
    DeflateInput deflate2(File{"filename"}, 5, 0);
    // case 3: error :-(
    InflateInput<DeflateInput<File>> inflate1(0,
        File{"filename"}, 9, 0);
    // case 4: ok
    InflateInput<DeflateInput<File>> inflate2(0,
        9, 0,
        "filename");

    return 0;
};
编译器错误为-std=c++2a,如下所示:

1.cpp: In instantiation of 'InflateInput<T>::InflateInput(int, Args ...) [with Args = {File, int, int}; T = DeflateInput<File>]':
1.cpp:35:26:   required from here
1.cpp:13:58: error: no matching function for call to 'DeflateInput<File>::DeflateInput(File&, int&, int&)'
   InflateInput(int header, Args ...args) : source(args...) {}
                                                          ^

错过完美的转发。试试下面

template<typename ...Args>
InflateInput(int header, Args&& ...args) : source(std::forward<Args&&>(args)...) {}
您可以复制相同的错误,如

DeflateInput deflate3(file, 5, 0)

错过完美的转发。试试下面

template<typename ...Args>
InflateInput(int header, Args&& ...args) : source(std::forward<Args&&>(args)...) {}
您可以复制相同的错误,如

DeflateInput deflate3(file, 5, 0)

这里的问题是没有正确转发参数

InflateInput<DeflateInput<File>> inflate1(0, File{"filename"}, 9, 0);
最简单的修复方法是在args上调用std::move,如

但是您真正应该做的是使用转发引用和std::forward完美地转发所有参数。这会将构造函数更改为

InflateInput(int header, Args&& ...args) : source(std::forward<Args>(args)...) {}

这里的问题是没有正确转发参数

InflateInput<DeflateInput<File>> inflate1(0, File{"filename"}, 9, 0);
最简单的修复方法是在args上调用std::move,如

但是您真正应该做的是使用转发引用和std::forward完美地转发所有参数。这会将构造函数更改为

InflateInput(int header, Args&& ...args) : source(std::forward<Args>(args)...) {}

错误消息是什么?在这两种情况下,T都是不可推断的上下文。您需要为DeflateInput提供模板参数。我看不出注释//案例1:ok或//案例2:ok在无法编译的情况下是如何成立的。此外,如果你真的想按照自己的意愿工作,这应该使用正确的转发引用。为什么DeflateInput有两个构造函数?@WhozCraig在C++17中是允许的。@变色龙感谢你通过添加C++17标记来澄清。错误消息是什么?在这两种情况下,T都是不可推断的上下文。您需要为DeflateInput提供模板参数。我看不出注释//案例1:ok或//案例2:ok在无法编译的情况下是如何成立的。此外,如果你真的想按照自己的意愿工作,这应该使用正确的转发引用。为什么DeflateInput有两个构造函数?@WhozCraig允许在C++17中使用。@Chameleon感谢你通过添加C++17标记来澄清。