C++ template constructor

C++TemplatesConstructor

C++ Problem Overview


I wish to have a non-template class with a template constructor with no arguments.

As far as I understand, it's impossible to have it (because it would conflict with the default constructor - am I right?), and the workaround is the following:

class A{
   template <typename U> A(U* dummy) {
   // Do something
   }
};

Maybe there is a better alternative for this (or a better workaround)?

C++ Solutions


Solution 1 - C++

There is no way to explicitly specify the template arguments when calling a constructor template, so they have to be deduced through argument deduction. This is because if you say:

Foo<int> f = Foo<int>();

The <int> is the template argument list for the type Foo, not for its constructor. There's nowhere for the constructor template's argument list to go.

Even with your workaround you still have to pass an argument in order to call that constructor template. It's not at all clear what you are trying to achieve.

Solution 2 - C++

You could use a templated factory function instead of a constructor:

class Foo
{
public:
    template <class T> static Foo* create() // could also return by value, or a smart pointer
    {
        return new Foo(...);
    }
...        
};

Solution 3 - C++

> As far as I understand, it's impossible to have it (because it would conflict with the default constructor - am I right?)

You are wrong. It doesn't conflict in any way. You just can't call it ever.

Solution 4 - C++

template<class...>struct types{using type=types;};
template<class T>struct tag{using type=T;};
template<class Tag>using type_t=typename Tag::type;

the above helpers let you work with types as values.

class A {
  template<class T>
  A( tag<T> );
};

the tag<T> type is a variable with no state besides the type it caries. You can use this to pass a pure-type value into a template function and have the type be deduced by the template function:

auto a = A(tag<int>{});

You can pass in more than one type:

class A {
  template<class T, class U, class V>
  A( types<T,U,V> );
};
auto a = A(types<int,double,std::string>{});

Solution 5 - C++

Some points:

  • If you declare any constructor(including a templated one), the compiler will refrain from declaring a default constructor.
  • Unless you declare a copy-constructor (for class X one that takes X or X& or X const &) the compiler will generate the default copy-constructor.
  • If you provide a template constructor for class X which takes T const & or T or T& then the compiler will nevertheless generate a default non-templated copy-constructor, even though you may think that it shouldn't because when T = X the declaration matches the copy-constructor declaration.
  • In the latter case you may want to provide a non-templated copy-constructor along with the templated one. They will not conflict. When X is passed the nontemplated will be called. Otherwise the templated

HTH

Solution 6 - C++

You could do this:

class C 
{
public:
    template <typename T> C(T*);
};
template <typename T> T* UseType() 
{
    static_cast<T*>(nullptr);
}

Then to create an object of type C using int as the template parameter to the constructor:

C obj(UseType<int>());

Since you can't pass template parameters to a constructor, this solution essentially converts the template parameter to a regular parameter. Using the UseType<T>() function when calling the constructor makes it clear to someone looking at the code that the purpose of that parameter is to tell the constructor what type to use.

One use case for this would be if the constructor creates a derived class object and assigns it to a member variable that is a base class pointer. (The constructor needs to know which derived class to use, but the class itself doesn't need to be templated since the same base class pointer type is always used.)

Solution 7 - C++

Here's a workaround.

Make a template subclass B of A. Do the template-argument-independent part of the construction in A's constructor. Do the template-argument-dependent part in B's constructor.

Solution 8 - C++

try doing something like

template<class T, int i> class A{

    A(){
          A(this)
    }

    A( A<int, 1>* a){
          //do something
    }
    A( A<float, 1>* a){
         //do something
    }
.
.
.
};

Solution 9 - C++

Just simple to add a dummy variable like

class A {
  template<typename T>
  A(const T&, int arg1, int arg2);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionYippie-Ki-YayView Question on Stackoverflow
Solution 1 - C++James McNellisView Answer on Stackoverflow
Solution 2 - C++KeatsPeeksView Answer on Stackoverflow
Solution 3 - C++Johannes Schaub - litbView Answer on Stackoverflow
Solution 4 - C++Yakk - Adam NevraumontView Answer on Stackoverflow
Solution 5 - C++Armen TsirunyanView Answer on Stackoverflow
Solution 6 - C++TolliView Answer on Stackoverflow
Solution 7 - C++Joshua ChiaView Answer on Stackoverflow
Solution 8 - C++user2616927View Answer on Stackoverflow
Solution 9 - C++vrqqView Answer on Stackoverflow