我有一个variant
课程。它有一对构造函数:
/// Construct and fill.
template <typename T>
inline
variant (const T& t)
{
YYASSERT (sizeof (T) <= S);
new (buffer.raw) T(t);
}
template <typename T>
inline
variant (T&& t)
{
YYASSERT (sizeof (T) <= S);
new (buffer.raw) T(std::move(t));
}
现在我在这段代码中调用了那些构造函数:
parser::symbol_type
parser::make_IDENTIFIER (const Wide::ParsedFile::Identifier*& v)
{
return symbol_type (token::IDENTIFIER, v);
}
symbol_type
在此特定构造函数中使用variant
作为第二个参数,并且隐式转换v
。
但是,MSVC将尝试使用rvalue引用构造函数而不是使用其他构造函数,从而在尝试new
引用时导致编译错误。为什么会这样,我怎么能让它停止?
答案 0 :(得分:3)
通常不应重载模板T&&
函数。你应该改为具有转发的单一功能:
template <typename T>
inline
variant (T&& t)
{
typedef typename std::remove_reference<T>::type Tr;
YYASSERT (sizeof (Tr) <= S);
new (buffer.raw) Tr(std::forward<T>(t));
}
这具有两个重载功能,同时避免了选择错误的问题。
我相信(不是肯定的)这些是你的重载集中的两个变体:
varaint<const Wide::ParsedFile::Identifier*>(const Wide::ParsedFile::Identifier*const&)
varaint<const Wide::ParsedFile::Identifier*&>(const Wide::ParsedFile::Identifier*&)
第二个胜利是因为它比第一个更专业(我做了一个有根据的猜测,我不是100%肯定的。)
答案 1 :(得分:0)
第二个模板将是更好的匹配,因为const
说明符位于函数和第一个构造函数的不同位置。
在第一次重载中,您将推导出T为
const Wide::ParsedFile::Identifier*
然后创建对该类型的const引用。这增加了一个额外的常量。