Search code examples
c++rvalue-referencelvaluetype-deduction

Type of member variable should depend on constructor argument's type


I try to define a class A as follows:

template< typename T >
class A
{
  public:
    A( T elem )
      : _elem( elem )
    {}

  private:
    TYPE _elem; // "TYPE" should be either "T" in case "elem" is an r-value or "T&" in case "elem" is an l-value.
};

Here, I want _elem to have either the type T in case that the constructor's argument elem is an r-value or the type T& in case elem is an l-value.

Does anyone know how this can be implemented?


Solution

  • Until we get template argument deduction for class templates, you'll need to use a helper function for this:

    template <typename T>
    auto make_a (T&& elem) {
        return A<T>{std::forward<T>(elem)};
    }
    

    This uses a forwarding reference to deduce whether the argument is an lvalue or rvalue and constructs the A by perfectly forwarding the argument. Taking int as an example, if an lvalue is passed, T will be int&, and if an rvalue is passed, T will be int.

    Your A template should just look like this:

    template< typename T >
    class A
    {
      public:
        A( T elem )
          : _elem( elem )
        {}
    
      private:
        T _elem;
    };
    

    You could make make_a a friend and make the constructor private if you only want to allow construction from the factory method.