C++ 强制编译器使用const T&;选择复制构造函数;作为参数

C++ 强制编译器使用const T&;选择复制构造函数;作为参数,c++,c++14,copy-constructor,C++,C++14,Copy Constructor,我正在编写一个类,其中有一个模板构造函数和复制构造函数。每次我想用非常量对象调用复制构造函数时,就会选择模板构造函数。如何强制编译器选择复制构造函数 以下是mcve: #include <iostream> struct foo { foo() { std::cout << "def constructor is invoked\n"; } foo(const foo& other) {

我正在编写一个类,其中有一个模板构造函数和复制构造函数。每次我想用非常量对象调用复制构造函数时,就会选择模板构造函数。如何强制编译器选择复制构造函数

以下是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);
}
#包括
结构foo
{
foo()
{

std::cout添加另一个构造函数:

foo(foo& other) : foo( const_cast<const foo&>(other))  // for non-const lvalues
{
}

添加另一个构造函数:

foo(foo& other) : foo( const_cast<const foo&>(other))  // for non-const lvalues
{
}

问题是
first
是可变的,因此对它的引用是
foo&
,它比
const foo&
更容易绑定到通用引用
T&

想必,您打算
T
是任何非foo类

在这种情况下,如果欺骗向编译器表达了意图,而不必编写大量虚假的重载,则使用一点
enable_

#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);
}

问题是
first
是可变的,因此对它的引用是
foo&
,它比
const foo&
更容易绑定到通用引用
T&

想必,您打算
T
是任何非foo类

在这种情况下,如果欺骗向编译器表达了意图,而不必编写大量虚假的重载,则使用一点
enable_

#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);
}

我对右值引用有专门的定义。还有其他方法吗?我相信
static\u cast
是可以的,因为使对象更常量是合法的。我已经有很多强制转换,但想看看是否有其他方法。
static\u cast
肯定可以,但我担心如果我更改类型;例如,通过从基类型转换为派生类型。这就是为什么我使用
const_cast
;只是为了让我自己和编译器明白,只有常量应该更改。我对右值引用有专门化。还有其他方法吗?我相信
static_cast
是可以的,因为使对象更为常量是合法的。我已经有很多强制转换,但想看看是否还有其他方法。
static\u cast
肯定可以,但我担心如果我更改类型,将来会破坏代码;例如,通过从基类型强制转换为派生类型。这就是为什么我使用
const\u cast
,只是为了让我清楚如果,对编译器来说,只有常量应该改变,那么在调用ctor执行任务时,不应该将参数强制转换为
const&foo
?ctor是用于常量参数的,所以请提供一个。@PeterA.Schneider,我正在编写
std::variant
。我认为人们不会喜欢强制转换。我想用一种方式保持用户端干净,以避免所有错误这些诡计是为转发构造函数提供一个虚拟的第一个参数,因此不存在混淆的可能性。这可能有助于更清楚地考虑您想要什么。是否要禁止所有类似于
foo
T
的模板构造函数?(
foo&
foo&
const foo&
volatile foo&
,…)只要启用一点
if
,或者在存在可行的非模板构造函数的特定情况下仅仅禁止模板构造函数,这应该足够简单了。(我认为后者是不可能的)@M.M,
std::variant
支持没有伪第一个参数的模板构造函数。我想编写一个尽可能严格符合标准的实现。调用ctor执行任务时不应该将参数强制转换为
const&foo
吗?ctor用于const args,所以提供一个。@PeterA.Schneider,我正在编写
>std::variant
。我不认为人们会喜欢强制转换。我想保持用户端的清洁避免所有这些恶作剧的一种方法是为转发构造函数提供一个虚拟的第一个参数,因此不存在混淆的可能性。这可能有助于更清楚地考虑您想要什么。是否要全面禁止模板构造函数
T
类似于
foo
?(
foo&
foo&
const foo&
volatile foo&
,…)这应该很简单,只要启用一点
就可以了。或者在有可行的非模板构造函数的特定情况下,仅仅禁止模板构造函数?(我认为后者是不可能的)@M.M,
std::variant
支持没有伪第一个参数的模板构造函数。我想编写尽可能严格符合标准的实现。