C ++ 0x perfect forwarding preventing ctor copying?

Using MSVC2010 ...

I have a structure that wraps std :: string, with the standard ctor movement, as well as a perfect ctor forwarding to redirect the argument to std :: string ctor.

struct Wrapper
{
  std::string value;

  Wrapper()
  {
  }

  Wrapper( Wrapper const& rhs )
    :value(rhs.value)
  {
  }

  Wrapper( Wrapper&& rhs )
    :value(std::move(rhs.value))
  {
  }

  Wrapper& operator=( Wrapper const& rhs )
  {
    value = rhs.value;
    return *this;
  }

  Wrapper& operator=( Wrapper&& rhs )
  {
    value = std::move(rhs.value);
    return *this;
  }


  template<typename StringT>
  Wrapper( StringT&& value )
    :value(std::forward<StringT>(value))
  {
  }
};

However, now it seems that I can not copy-build Wrapper from another shell

Wrapper w0;
Wrapper w1(w0);

This results in a compilation error indicating a perfect ctor forwarding, stating that it cannot convert Wrapper to std :: string. Is this the right behavior? Shouldn't the compiler invoke a copy of ctor compared to template overload?

1>t:\depot\warp\code\apps\pf_test\main.cpp(56): error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(const std::basic_string<_Elem,_Traits,_Ax> &)' : cannot convert parameter 1 from 'Wrapper' to 'const std::basic_string<_Elem,_Traits,_Ax> &'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          Reason: cannot convert from 'Wrapper' to 'const std::basic_string<_Elem,_Traits,_Ax>'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>          t:\depot\warp\code\apps\pf_test\main.cpp(63) : see reference to function template instantiation 'Wrapper::Wrapper<Wrapper&>(StringT)' being compiled
1>          with
1>          [
1>              StringT=Wrapper &
1>          ]
1>

If I define another copy of ctor that accepts a non-constant reference to Wrapper (shown below), then everything seems fine ... Is this the way forward? Or am I ruining something? Or is this a bug in VS2010?

  Wrapper( Wrapper& rhs )
    :value(rhs.value)
  {
  }
+3
1

, .

- . (Wrapper(StringT&&) StringT = Wrapper& Wrapper(Wrapper&)) , , .

- std::enable_if <type_traits>:

template <typename StringT>
Wrapper(StringT&& value,
  typename std::enable_if<
    !std::is_same<
      StringT,
      Wrapper&
    >::value
  >::type* = 0)
  : value(std::forward<StringT>(value))
{ }

, .

+4

All Articles