У меня есть шаблон класса с тремя конструкторами, и один из них — шаблон функции.
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.
Очевидно, я путаю компилятор, когда присутствует конструктор массива. Таким образом, вместо того, чтобы позволить компилятору автоматически выводить, я попытался указать параметр шаблона для конструктора массива, чтобы он обнаруживал только в отличие от обычной функции, параметры шаблона не могут быть специально определены.
Я думал о введении фиктивного параметра в конструкторе массива для дифференциации перегрузки, но это не кажется хорошим.
Есть ли другой способ решить эту проблему? Любая подсказка приветствуется.
Сделайте ваш параметр конструктора указателя для 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;
это ссылка, вы должны удалить &
там.
Других решений пока нет …