yuan
yuan

Reputation: 2534

how and when to use constructor function templates?

I'm confused about the sentence below,I understand the example they used for conversion member function but not understand the constructor member function templates occasions,helpful example given by Mankarse.

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 N3242

struct A {
    template <class T> operator T*();
};
template <class T> A::operator T*(){ return 0; }
template <> A::operator char*(){ return 0; } // specialization
template A::operator void*(); // explicit instantiation

int main() 
{
   A a;
   int *ip;
   ip = a.operator int*(); // explicit call to template operator
   // A::operator int*()
}

The template-arguments for a member function of a class template are determined by the template-arguments of the type of the object for which the member function is called. --14.5.1.1.2 N3242

So I need to deduct the template-argument by myself or use a wrapper.
example given by libstdc++ when reading standard library:

template<typename _Container>
class back_insert_iterator
: public iterator<output_iterator_tag, void, void, void, void>
{
   protected:
      _Container* container;
   public:
       explicit
       back_insert_iterator(_Container& __x) : container(&__x) { }
}
/*
 *it use a wrapper :
 */
template<typename _Container>
inline back_insert_iterator<_Container>
back_inserter(_Container& __x)
{ return back_insert_iterator<_Container>(__x); }

Upvotes: 2

Views: 1369

Answers (2)

barney
barney

Reputation: 2202

You can use intermediary template class to make explicit parameter to ctor - and it will deduce your desired type

#include <iostream>
using namespace std;

template <typename T> struct tag { using type = T;};

class My {
public:
    template <typename T> My(tag<T>) {
        cout << "ctor of " << typeid(T).name();
    }
};

int main(int argc, const char * argv[]) {

    auto a = My(tag<int>());
}

Upvotes: 1

Mankarse
Mankarse

Reputation: 40633

You can never provide an explicit template argument list to constructor templates. Constructor templates must always have their arguments deduced:

struct A {
    template<typename U> A() {}
};
template <typename T>
struct B {
    B() {}
};
struct C {
    template<typename U> C(U t) {}
};
template <typename T>
struct D {
    template<typename U> D(U t) {}
};

int main()
{
    //auto a1 = A<int>{}; //illegal -- A is not a template
    //A can never be instantiated...

    auto b = B<int>{}; //default-constructs a B<int>

    //auto c = C<double>{1.}; //illegal - C not a template

    //Constructs a C, deduces `U = double` constructor:
    auto c = C{1.};
    //Constructs a D<int>, deduces `U = double` constructor:
    auto d = D<int>{1.};
}

Upvotes: 5

Related Questions