强制编译器选择const T&作为参数的复制构造函数

Inc*_*ble 6 c++ copy-constructor c++14

我正在写一个类,我有一个模板化的构造函数和复制构造函数.每次我想用非const对象调用复制构造函数时,都会选择模板化构造函数.如何强制编译器选择复制构造函数?

这是mcve:

#include <iostream>

struct foo
{
    foo()
    {
        std::cout << "def constructor is invoked\n";
    }

    foo(const foo& other)
    {
        std::cout << "copy constructor is invoked\n";
    }

    template <typename T>
    foo(T&& value)
    {
        std::cout << "templated constructor is invoked\n";
    }
};

int main()
{
    foo first;
    foo second(first);
}
Run Code Online (Sandbox Code Playgroud)

删除功能不是我想要的.

Aar*_*aid 8

添加另一个构造函数:

foo(foo& other) : foo( const_cast<const foo&>(other))  // for non-const lvalues
{
}
Run Code Online (Sandbox Code Playgroud)

first在您的示例代码对象是一个非const左值,因此编译器倾向于foo(foo&)过度foo(const &).前者由模板(with T=foo&)提供,因此被选中.

这个解决方案涉及提供一个(非模板)构造函数foo(foo&),然后通过将构造函数转换为const-to-const来将构造委托给复制构造函数.

更新,我刚刚意识到foo模板也将采用右值.这里有很多选项,但我想最简单的方法是添加一个委托foo(foo&&),类似于上面的一个

foo(foo&& other) : foo( const_cast<const foo&>(other))  // for rvalues
{
}
Run Code Online (Sandbox Code Playgroud)


Ric*_*ges 5

问题是它first是可变的,因此对它foo&的引用T&&更容易与通用引用结合const foo&.

据推测,你打算T做任何非foo课程吗?

在这种情况下,一点点的enable_ifchicanry表达了对编译器的意图,而不必编写一系列虚假的重载.

#include <iostream>

struct foo
{
    foo()
    {
        std::cout << "def constructor is invoked\n";
    }

    foo(const foo& other)
    {
        std::cout << "copy constructor is invoked\n";
    }

    template <typename T, std::enable_if_t<not std::is_base_of<foo, std::decay_t<T>>::value>* = nullptr>
    foo(T&& value)
    {
        std::cout << "templated constructor is invoked\n";
    }

};

int main()
{
    foo first;
    foo second(first);
    foo(6);
}
Run Code Online (Sandbox Code Playgroud)

预期产量:

def constructor is invoked
copy constructor is invoked
templated constructor is invoked
Run Code Online (Sandbox Code Playgroud)