Can the template parameters of a constructor be explicitly specified?
Asked Answered
H

4

49

A constructor of a class can be a template function. At the point where such a constructor is called, the compiler usually looks at the arguments given to the constructor and determines the used template parameters from them. Is there also some syntax to specify the template parameters explicitly?

A contrived example:

struct A {
   template<typename T>
   A() {}
};

Is there a way to instantiate this class? What is the syntax to explicitly specify the constructor's template parameters?

My use case would be a problem were the compiler doesn't seem to find the correct templated constructor. Explicitly specifying the template parameters would probably generate more useful error messages or even resolve the problem.

Hurtado answered 18/5, 2010 at 23:18 Comment(2)
Explicitly specifying template arguments for constructors only works in explicit specializations, instantiations, out of line definitions and friend declarations of the constructor.Piezoelectricity
template <class TArg> struct A { template<typename T = TArg> A() {} }; - works fine for me. But of course now we have template class.Nadabas
L
49

No. The C++03 standard says:

[Note: because the explicit template argument list follows the function template name, and because conversion member function templates and constructor member function templates are called without using a function name, there is no way to provide an explicit template argument list for these function templates.] (§14.5.2/5)

Laurentian answered 18/5, 2010 at 23:22 Comment(0)
D
13

There is another solution for transfering type information to templated constructors which can't take a value of this type as an argument:

template<class T>
struct id
{};

struct A {
  template<class T>
  A(id<T>);
};

A a=id<int>();

Edit:

Please note: A a(id<int>()); will not work, because of most vexing parse. It would be interpreted as an function declaration. See this question for further explanation.

Diallage answered 5/6, 2013 at 15:45 Comment(1)
What about A a{id<int>()); ?Cramer
G
8

As a workaround: you can define a templated static factory function, which in turn would return an instance using a private constructor.

struct A {
    template<typename T>
    static A create() {
        return A();
    }
private:
    A() {}
};

You then get new instances of A like this:

auto a1 = A::create<int>();
auto a2 = A::create<long>();
Gradus answered 29/12, 2018 at 21:45 Comment(0)
A
2

no, you cannot instantiate that class using that constructor. BUT:



struct A
{
  template < typename T >
  A(T const&);
};

Now you can.

Abadan answered 18/5, 2010 at 23:19 Comment(5)
I don't quite understand the answer... how is it related to the question?Conjunctivitis
It shows how you can do it. It just so happens that you can't do it the way the question asked.Twirp
Too bad comments can't be demoted. That one is far from "great".Abadan
You can also do it in a way so that the ctor doesn't appear to need args: template <typename T> A(const T* = NULL); Be sure to keep that space between * and = or you'll wonder for days what the error message means...Assemblyman
I don't suppose the person who up-voted that actually tried it. You can't do that because the compiler is unable to figure out what T is meant to be without the argument.Abadan

© 2022 - 2024 — McMap. All rights reserved.