-2

I need to implement a template function which would allow me to create an instance of arbitrary class using arbitrary constructor with any possible parameters which can be any combination of lvalues and rvalues.

Lets say I have two classes - A and B - which are as follows:

class A
{
public:

A(){}


};

class B
{
    A& a1; // I want to be able to call non-constant methods and modify object
    const A& a2; // This I need only as const member
    int i; //can be initialized with a temporary object

    public:

    B(A& a1_, const A& a2_, int i_) : a(a_), a2(a2_), i(i_) {}
};

I tried to implement something like below but it would only allow me to use lvalues (named objects) and I will not be able to pass temporary objects. Adding const keyword partly solves the issue but disallows ability to modify objects which may be required.

template <typename TType, typename ... TArgs>
TType create(TArgs&... args)
{
    return TType(args...);
}

I want to use 'create' function like this:

int main()
{
   A a1;
   A a2;
   //function takes both lvalue and rvalue
   B b = create<B>(a1, a2, 1);
}

Could someone please suggest a possible solution?

senx
  • 630
  • 9
  • 18

2 Answers2

2

As commented above by Alan Stokes, you can use forwarding references to receive lvalue and rvalue expressions:

template <typename TType, typename ... TArgs>
TType create(TArgs&&... args)
{
    return TType(std::forward<TArgs>(args)...);
}
Cosme
  • 191
  • 2
  • 6
0

Could someone please suggest a possible solution?

You just have a few typos. Especially you don't need to pass all arguments by non const reference as TArgs& to the create() function. The compiler would match the best fitting types (references) already.

class B
{
    A& a1; // I want to be able to call non-constant methods and modify object
    const A& a2; // This I need only as const member
    int i; //can be initialized with a temporary object

    public:

    B(A& a1_, const A& a2_, int i_) : a1(a1_), a2(a2_), i(i_) {}
       // ^                            ^  ^
};

template <typename TType, typename ... TArgs>
TType create(TArgs... args)
               // ^ Remove the reference here
{
    return TType(args...);
}

int main()
{
   A a1;
   const A a2;
// ^^^^^
   //function takes both lvalue and rvalue
   B b = create<B>(a1, a2, 1);
}

See the fully compiling version live here.


Of course using a move reference as stated in other answers/comments would also fix the errors (besides the a for a1 typos.):

template <typename TType, typename ... TArgs>
TType create(TArgs&&... args)
{
    return TType(std::forward<TArgs>(args)...);
}

See another live example.

user0042
  • 7,917
  • 3
  • 24
  • 39