The problem is that your constructor template is a better match than your copy constructor:
// Copy constructor
WrappedStack( const WrappedStack &other )
// Constructor template
template <typename S>
WrappedStack( S &stack )
When instantiated with an object of type WrappedStack<T>
(where T
is the class template parameter), the instantiated signature of the constructor template will look like:
WrappedStack( WrappedStack<T> &stack )
This is better match than the copy constructor if the type of the argument is not const
-qualified, because it does not require a const
conversion. Therefore, the constructor template will be picked by overload resolution, and its body will be instantiated, causing the error you are experiencing.
To force the compiler to use the copy constructor when appropriate, you could use SFINAE to cause a substitution failure when instantiating the constructor template with an object of type WrappedStack<T>
, or of a type which is implicitly convertible to WrappedStack<T>
. For instance:
#include <type_traits>
template<
typename S,
typename std::enable_if<
!std::is_convertible<S, WrappedStack<T> const&>::value
>::type* = nullptr>
WrappedStack( S &stack ) : __stack( new wrapped_stack_t<S, T>( stack ) ) {}
See a live example of this succesfully compiling.