强制编译器选择以 const T& 作为参数的复制构造函数
Force compiler to choose copy constructor with const T& as a parameter
我正在编写一个 class,其中我有一个模板化构造函数和复制构造函数。每次我想用非 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);
}
删除函数不是我想要的
添加另一个构造函数:
foo(foo& other) : foo( const_cast<const foo&>(other)) // for non-const lvalues
{
}
示例代码中的 first
对象是一个非常量左值,因此编译器更喜欢 foo(foo&)
而不是 foo(const &)
。前者由模板提供(带T=foo&
),因此被选中。
此解决方案涉及为 foo(foo&)
提供一个(非模板)构造函数,然后通过将构造函数转换为常量引用来将构造委托给复制构造函数
Update,我刚刚意识到 foo
右值也将被模板采用。这里有很多选项,但我想最简单的是也为 foo(foo&&)
添加一个委托,类似于上面的
foo(foo&& other) : foo( const_cast<const foo&>(other)) // for rvalues
{
}
问题在于 first
是可变的,因此对它的引用是 foo&
,它比 const foo&
更容易绑定到通用引用 T&&
。
据推测,您打算 T
是任何非 foo class?
在这种情况下,一点点 enable_if
欺骗可以向编译器表达意图,而不必编写大量虚假重载。
#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);
}
预期输出:
def constructor is invoked
copy constructor is invoked
templated constructor is invoked
我正在编写一个 class,其中我有一个模板化构造函数和复制构造函数。每次我想用非 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);
}
删除函数不是我想要的
添加另一个构造函数:
foo(foo& other) : foo( const_cast<const foo&>(other)) // for non-const lvalues
{
}
示例代码中的 first
对象是一个非常量左值,因此编译器更喜欢 foo(foo&)
而不是 foo(const &)
。前者由模板提供(带T=foo&
),因此被选中。
此解决方案涉及为 foo(foo&)
提供一个(非模板)构造函数,然后通过将构造函数转换为常量引用来将构造委托给复制构造函数
Update,我刚刚意识到 foo
右值也将被模板采用。这里有很多选项,但我想最简单的是也为 foo(foo&&)
添加一个委托,类似于上面的
foo(foo&& other) : foo( const_cast<const foo&>(other)) // for rvalues
{
}
问题在于 first
是可变的,因此对它的引用是 foo&
,它比 const foo&
更容易绑定到通用引用 T&&
。
据推测,您打算 T
是任何非 foo class?
在这种情况下,一点点 enable_if
欺骗可以向编译器表达意图,而不必编写大量虚假重载。
#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);
}
预期输出:
def constructor is invoked
copy constructor is invoked
templated constructor is invoked