Явное задание шаблонного параметра конструктора

Рейтинг: 2Ответов: 3Опубликовано: 30.01.2023

Допустим, есть класс с конструктором. У конструктора есть шаблонный параметр:

template<typename T> class A {
    T v;
public:
    template<typename U> A(T p,U u) : v(p)
    {
        std::cout << u << v << std::endl;
    }
};

Тип U может быть выведен:

int main()
{
    A<int> b(2,'A');            // Ok, U = char
    auto x = A<int>::A(1,'A');  // Ok, U = char
}

А можно ли задать его явно, не через аргумент конструктора? Как-то так:

int main()
{
    A<int,char> b(2,'A');   // не работает
    A<int><char> b(2,'A');  // не работает
    auto y= A<int>::A<char>(2, 'A');   // не работает
}

Ответы

▲ 3

У конструкторов нельзя выбирать, а простых методов можно. Просто укоротите конструктор функционально и вызовите шаблонный метод.

#include <iostream>
template<typename T> 
class A {
    T v;
public:
  A(T p) : v(p) { }
  template<typename U>
  A & Constructor(U u){
    std::cout << u <<' '<< v << std::endl; 
    return * this ;
  }
} ;

int main (){

  A<int>(1).Constructor<double>(3);

  A<int> a(2) ;
  a.Constructor<char>('4'); 

}

Это просто принцип. А теперь красота:


Для красоты можете создать шаблонный класс только для конструкторов :

#include <iostream>
template<typename T> 
class A {
    T v;
protected :
  A(T p) : v(p) { }
  template<typename U>
  A & Constructor(U u){
    std::cout << u <<' '<< v << std::endl; 
    return * this ;
  }
} ;

template<typename T,typename U> 
class B : public A<T> {
public:
    B ( T v , U u ) : A<T> ( v ) {
        A<T>::Constructor(u);
    }
} ;

int main (){
  B<char,double> b ( '1' , 2.5 ) ;
  A<char> & a = b ; 
}

Объект B включает в себя класс A и он будет работать точно так-же как и класс A. Вызов внутренних шаблонных методов будет спрятан от глаз пользователя.

▲ 1

В таком виде - нет. Но можно, если измените сигнатуру шаблона.
Сделайте параметр шаблона конструктора параметром шаблона всего класса.

template<typename T, typename U> 
class A 
{
    T v;
public:
    A(T p,U u) : v(p)
    {
        std::cout << u << v << std::endl;
    }
};

int main()
{
    A<int,char> b(2,'A');   // работает
    A c(3,'A'); // автовыведение типа
}
▲ 1

В продолжение идеи AlexGlebe. Так нельзя забыть вызвать Constructor:

#include <iostream>
template<typename T>
class A {
    T v;
    A(T p) : v(p) { } //Приватный конструктор
public:
    template<typename U>
    static A constructor(T p, U u){
        A out(p);
        //Constructor
        std::cout << u <<' '<< out.v << std::endl;
        return out;
    }
};

int main (){
    A<int> a = A<int>::constructor<char>(2,'A');
    return 0;
}