为什么可变参数模板构造函数比复制构造函数更好地匹配?

kpx1894

以下代码无法编译:

#include <iostream>
#include <utility>

struct Foo
{
    Foo() { std::cout << "Foo()" << std::endl; }
    Foo(int) { std::cout << "Foo(int)" << std::endl; }
};

template <typename T>
struct Bar
{
    Foo foo;

    Bar(const Bar&) { std::cout << "Bar(const Bar&)" << std::endl; }

    template <typename... Args>
    Bar(Args&&... args) : foo(std::forward<Args>(args)...)
    {
        std::cout << "Bar(Args&&... args)" << std::endl;
    }
};

int main()
{
    Bar<Foo> bar1{};
    Bar<Foo> bar2{bar1};
}

编译器错误提示我,编译器正在尝试使用可变参数模板构造函数而不是复制构造函数:

prog.cpp: In instantiation of 'Bar<T>::Bar(Args&& ...) [with Args = {Bar<Foo>&}; T = Foo]':
prog.cpp:27:20:   required from here
prog.cpp:18:55: error: no matching function for call to 'Foo::Foo(Bar<Foo>&)'
  Bar(Args&&... args) : foo(std::forward<Args>(args)...)

为什么编译器会这样做以及如何解决?

巴里

这个电话:

Bar<Foo> bar2{bar1};

在其重载集中有两个候选:

Bar(const Bar&);
Bar(Bar&);       // Args... = {Bar&}

从[over.ics.rank]确定一种转换顺序是否比另一种转换顺序更好的方法之一是:

如果满足以下条件,则标准转换序列S1比标准转换序列S2更好。

— [...]
— S1和S2是引用绑定(8.5.3),引用所引用的类型是相同的类型(顶级cv -qualifiers除外)以及引用由S2初始化的类型引用比由S1初始化的引用所引用的类型更具cv资格。[示例:

int f(const int &);
int f(int &);
int g(const int &);
int g(int);

int i;
int j = f(i);    // calls f(int &)
int k = g(i);    // ambiguous

—结束示例]

转发引用可变参数构造函数是更好的匹配项,因为其引用绑定(Bar&)的cv限定性低于复制构造函数的引用绑定(const Bar&)。

就解决方案而言,您可以随时将其排除在候选集之外Args...,而应该使用SFINAE调用该副本或移动构造函数:

template <typename... > struct typelist;

template <typename... Args,
          typename = std::enable_if_t<
              !std::is_same<typelist<Bar>,
                            typelist<std::decay_t<Args>...>>::value
          >>
Bar(Args&&... args)

如果Args...是一BarBar&Bar&&const Bar&,那么typelist<decay_t<Args>...>将是typelist<Bar>-这就是我们要排除的情况下。任何其他设置Args...都可以。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

我的可变参数模板构造函数隐藏了复制构造函数,防止类被复制

编写可变参数模板构造函数

为什么可变参数模板找不到合适的构造函数?

如何删除可变参数模板构造函数的复制/移动实例

带有可变参数模板构造函数的推导指南和可变参数类模板-参数包长度不匹配

可变参数模板构造函数优先级

通过可变参数模板的C ++ 11构造函数继承

限制可变参数模板类中的构造函数访问

可变参数模板递归构造函数问题

在C ++中没有匹配的构造函数来初始化可变参数模板

没有用于初始化可变参数模板类的匹配构造函数

值包装器的可变参数模板构造函数的类构造函数优先级

C ++可变参数模板构造函数和通用构造函数

为什么不能为构造函数模板指定模板参数

通过转发构造函数参数,基于可变参数模板构造一个mixin

为每个可变参数模板参数调用函数,并将结果作为构造函数参数传递

从具有可变参数模板构造函数的类型构造 std::function 对象

C ++-通过enable_if_t推导参数包(可变模板)构造函数和复制构造函数

具有多个参数包的可变参数模板构造函数

具有相同类型的可变参数模板参数的构造函数无法编译

省略号作为可变参数模板之外的构造函数参数

仅当给出的参数超过 n 时,如何启用可变参数模板构造函数?

将原子传递给可变参数时,为什么要调用复制构造函数?

为什么在迭代可变参数模板参数时必须使用其他构造?

在可变参数模板类的构造函数中初始化元组成员

如何在C ++中调用可变参数模板构造函数?

具有左值和右值的可变参数模板类构造函数

可变数量的构造函数参数取决于整数模板

从可变参数模板数组引用构造函数初始化双嵌套std :: array