0

我有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将 avariant作为此特定构造函数中的第二个参数,并且v正在被隐式转换。

但是,MSVC 将尝试使用右值引用构造函数而不是使用其他构造函数,从而在尝试new引用时导致编译错误。为什么会这样,我怎样才能让它停止?

4

2 回答 2

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% 肯定的)。

于 2011-08-04T16:20:30.073 回答
0

第二个模板将是更好的匹配,因为说明const符在您的函数和第一个构造函数中的不同位置。

在第一个重载中,您将 T 推导出为

const Wide::ParsedFile::Identifier*

然后创建对该类型的 const 引用。这增加了一个额外的常量。

于 2011-08-04T16:27:33.243 回答