6

Is it possible to call a constructor with template arguments if the class is a template too?

#include <stdio.h>
#include <iostream>

template <class A>
struct Class
{
  template <class B>
  Class(B arg) { std::cout << arg << std::endl; }
};

int main()
{
  Class<int> c<float>(1.0f);
  Class<int>* ptr = new Class<int><float>(2.0f);
  return 0;
}

edit: so I guess the only way to call a specific template constructor is to call it with casted paramterers to the template type you want:

#include <stdio.h>
#include <iostream>

template <class A>
struct Class
{
  template <class B>
  Class(B arg) { std::cout << arg << std::endl; }

  Class(double arg) { std::cout << "double" << std::endl; }
  Class(float arg) { std::cout << "float" << std::endl; }
};

int main()
{
  Class<int> c(1.0f);
  Class<int>* ptr = new Class<int>((double)2.0f);
  return 0;
}

// this outputs: float double

edit2: but what happens to constructor template arguments that are not part of the constructor arguments itself ?

template <class B, class C>
Class(B arg) { /* how do you specify ?? C */ }
costy.petrisor
  • 783
  • 7
  • 17
  • Note that your constructor should be able to infer the type of the argument you pass to him without having to specify it explicitely. – ereOn Jun 15 '11 at 12:09
  • Could you add some punctuation to the question? I'm not sure how to parse it! – juanchopanza Jun 15 '11 at 12:15
  • A possible duplicate of [this](http://stackoverflow.com/questions/2786946/c-invoke-explicit-template-constructor). Note that the outer class being a template is irrelevant. – n. m. could be an AI Jun 15 '11 at 12:28
  • I think edit2 deserved a question of his own. http://stackoverflow.com/questions/6358882/c-template-constructor-weirdness – costy.petrisor Jun 15 '11 at 13:59

4 Answers4

4

In the example you gave you actually don't need to explicitly give the template argument to invoke constructor like:

Class<int> c<float>(1.0f);

Simply providing argument as 1.0f is enough:

Class<int> c(1.0f);

Same thing is applicable for new example too. Having said that, I don't think constructor you can invoke explicitly using template argument (unlike normal function).

iammilind
  • 68,093
  • 33
  • 169
  • 336
2

edit2: but what happens to constructor template arguments that are not part of the constructor arguments itself ?

Then you can pass-in an argument that has it encoded

template<typename T> struct encodeType { };

struct A {
  template<typename T, typename U>
  A(T t, encodeType<U>) { }
};

A a(1, encodeType<float>());
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
1
Class<int> c(1.0f); //f in 1.0 makes it float type!
Class<int>* ptr = new Class<int>(2.0f);

This is enough. It will invoke the constructor which has template argument float. From the argument 1.0f, the compiler will deduce the type argument of the constructor template. Since 1.0f is float, so the type argument the compiler will deduce is float.

Likewise see these:

Class<int> c(1.0); //this will invoke Class<int><double>(double);
Class<int>* ptr = new Class<int>(2); //this will invoke Class<int><int>(int);
Nawaz
  • 353,942
  • 115
  • 666
  • 851
1

You need to explicitly state the template type that goes with the class itself (that's A in your example). But you don't need to say what type B is. The compiler knows from you passing 1.0f that B == float. There's nothing in the constructor call to help the compiler figure out what A is, so you have to tell it:

Class<int> c(1.0f);
Class<int>* ptr = new Class<int>(2.0f);
Michael Kristofik
  • 34,290
  • 15
  • 75
  • 125