开发者

Template type deduction problem

I've got a variant class. It has a pair of constructors:

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

Now I've called those constructors in this code:

parser::sy开发者_C百科mbol_type
parser::make_IDENTIFIER (const Wide::ParsedFile::Identifier*& v)
{
return symbol_type (token::IDENTIFIER, v);
}

symbol_type takes a variant as it's second argument in this specific constructor, and v is being implicitly converted.

However, MSVC will try to use the rvalue reference constructor instead of using the other constructor, resulting in a compilation error when it attempts to new a reference. Why is that, and how can I make it stop?


You generally should not overload a templated T&& function. You should instead have the single function which forwards:

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

This has the functionality of your two overloads, while avoiding the problem of picking the wrong one.

I believe (not positive) that these are the two variants in your overload set:

varaint<const Wide::ParsedFile::Identifier*>(const Wide::ParsedFile::Identifier*const&)
varaint<const Wide::ParsedFile::Identifier*&>(const Wide::ParsedFile::Identifier*&)

And the second one wins because it is more specialized than the first (I'm making an educated guess, I'm not 100% positive).


The second template would be a better match, because the const specifiers are in different places in your function and in the first constructor.

In the first overload you will have T being deduced as

const Wide::ParsedFile::Identifier*

And then creating a const reference to that type. That adds an extra const.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜