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

У меня есть шаблон класса с тремя конструкторами, и один из них — шаблон функции.

template<class T>
class TemplateOverLoading
{
public:
TemplateOverLoading(void){};
~TemplateOverLoading(void){};
//constructor that take reference
TemplateOverLoading(std::string& qName, T& qValue )
:   mName(qName),
mValue( &qValue)
{
std::cout << "Reference -> "<< *mValue <<"\n";
}

//Template constructor that takes array
template<class T, int N>
TemplateOverLoading(std::string& qName, T (&t)[N])
:   mName(qName),
mValue(t)
{
std::cout << "Array ->\n";
for(int i = 0; i < N; i++)
std::cout<< mValue[i];
std::cout << std::endl;
}

//Other constructor that take pointer
TemplateOverLoading(std::string& qName, T* qValue )
:   mName(qName),
mValue( qValue)
{
std::cout << "Pointer "<< *mValue <<"\n";
}
private:
T*               mValue;
//T*              mValueArray;
std::string&    mName;
};

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

Я пытаюсь вызвать конструктор следующим образом:

int init(10);
int intArray[10] = {0,1,2,3,4,5,6,7,8,9};
TemplateOverLoading<int> mInt(std::string("mInt"), init);
TemplateOverLoading<int> mIntArray( std::string("mIntArray"), intArray );

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

Выход:

(when pointer constructor is present)
Reference -> 10
Pointer 0

(when pointer constructor is not present)
Reference -> 10
Array ->
0123456789

Так что синтаксически это возможно и правильно, выводя размер массива N.

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

Я думал о введении фиктивного параметра в конструкторе массива для дифференциации перегрузки, но это не кажется хорошим.

Есть ли другой способ решить эту проблему? Любая подсказка приветствуется.

1

Решение

Сделайте ваш параметр конструктора указателя для T*& qValue,

TemplateOverLoading(std::string& qName, T*& qValue )
:   mName(qName),
mValue( qValue)
{
std::cout << "Pointer "<< *mValue <<"\n";
}

Делая это ссылкой на указатель, предотвращается распад массива на указатель и выбирается конструктор массива.

Кроме того, я не вижу, как ваш код компилируется, я вижу много ошибок:

Ваш конструктор шаблона имеет параметр class Tэто противоречит class T шаблона класса:

template<class T, int N>
TemplateOverLoading(std::string& qName, T (&t)[N])

Это должно быть изменено на что-то другое, чем class T, например class U:

template<class U, int N>
TemplateOverLoading(std::string& qName, U (&t)[N])

Ваши конструкторы также принимают неконстантная Ссылка lvalue, неконстантная ссылка не может привязываться к временным файлам, которые вы передаете в вызове конструктора, т.е. std::string("mIntArray"), Вы должны изменить его на const std::string& или возьмите это по значению. Также ваш член std::string& mName; это ссылка, вы должны удалить & там.

1

Другие решения

Других решений пока нет …