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

1

14

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?

Christianize answered 11/11, 2016 at 10:28 Comment(2)
I'm not clever enough to write this out for you, but you achieve this using template specialisation. Upvoted to attract attention.Shaylyn
I've had a need for this as well (when writing view classes)...Selfcontent
H
12

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.

Hards answered 11/11, 2016 at 10:37 Comment(4)
Why is std::move using in constructor of A?Transistor
When an r-value is passed, why is T then int and not int&&?Christianize
@Christianize that's just how the normal template deduction rules work. The int& deduction is a special-case.Hards
I think this deduction is now integrated in standard C++, en.cppreference.com/w/cpp/language/… (CTAD)Gentlemanatarms

© 2022 - 2024 — McMap. All rights reserved.