Конструктор шаблонов в шаблоне класса - как явно указать аргумент шаблона для второго параметра?

Конструктор шаблонов в шаблоне класса - как явно указать аргумент шаблона для второго параметра?

скомпилировать ошибку при попытке явного указания аргумента шаблона для конструктора 2. Как это сделать, если я действительно хочу явный конструктор вызовов 2?

Обратите внимание, что это та же самая ситуация для boost:: shared_ptr, когда вы хотите явно указать тип удаления.

N.B. Для функции non -construction foo() явно указывается, что работает нормально.

N.B Я знаю, что он отлично работает без указывает 2-й явным образом для конструктора 2 как вывод аргумента шаблона, как правило, просто отлично работает, мне просто интересно, как его явно указывать.

template<class T> class TestTemplate {
public:
    //constructor 1
    template<class Y> TestTemplate(T * p) {
        cout << "c1" << endl;
    }

    //constructor 2
    template<class Y, class D> TestTemplate(Y * p, D d) {
        cout << "c2" << endl;
    }

    template<class T, class B>
    void foo(T a, B b) {
        cout << "foo" << endl;
    }
};

int main() {
    TestTemplate<int> tp(new int());//this one works ok call constructor 1
    //explicit template argument works ok
    tp.foo<int*, string>(new int(), "hello");

    TestTemplate<int> tp2(new int(),2);//this one works ok call constructor 2

    //compile error when tried to explicit specify template argument for constructor 2
    //How should I do it if I really want to explicit call constructor 2?
    //TestTemplate<int*, int> tp3(new int(), 2); //wrong
    //TestTemplate<int*> tp3<int*,int>(new int(), 2); //wrong again

    return 0;
}

Ответ 1

Исправляя ваш код, будет работать следующее:

template<class T> class TestTemplate {
public:
    //constructor 1
    template<class Y> TestTemplate(Y * p) {
        cout << "c1" << endl;
    }

    //constructor 2
    template<class Y, class D> TestTemplate(Y * p, D d) {
        cout << "c2" << endl;
    }

    template<class A, class B>
    void foo(A a, B b) {
        cout << "foo" << endl;
    }
};

int main() {
    TestTemplate<int> tp(new int());

    tp.foo<int*, string>(new int(), "hello");

    TestTemplate<int> tp2(new int(),2);
}

Вы не можете использовать T для параметра шаблона шаблона и параметра шаблона конструктора. Но, чтобы ответить на ваш вопрос, из [14.5.2p5]:

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

Поэтому вы не можете явно указывать аргументы шаблона для конструктора.

Ответ 2

Вы не можете явно указывать аргументы шаблона для конструктора, потому что конструктор не имеет имени сам по себе, поэтому нет синтаксиса для него.

Но вы можете убедиться, что правильные аргументы шаблона выведены,

  • листинг фактических аргументов и/или

  • вводя "искусственные" дополнительные аргументы просто для передачи информации о типе, если это необходимо, и/или

  • используйте функцию factory.

Например, вы можете определить

template< class Type > struct TypeCarrier{ typedef Type T; };

struct MyClass
{
    template< class Type >
    MyClass( TypeCarrier< Type > ) { ... }
};

...
MyClass o( TypeCarrier<int>() );

Но не увлекайтесь такими методами.

Вместо этого, если появляется очевидная необходимость явно указывать аргументы шаблона конструктора, подумайте, действительно ли дизайн действительно звучит?

Возможно, вы можете использовать более простой дизайн, если будете размышлять над тем, что это значит для s?

Ответ 3

Вы можете явно указать аргументы шаблона для своих вызовов на foo, потому что эти функции-члены foo имеют имена - и аргументы шаблона являются частью этого имени.

Это не работает с конструкторами, потому что конструктор не имеет имени. Вы не можете (напрямую) вызвать конструктор. Конструктор, конечно, вызывается при создании объекта, но вызов генерируется кодом.