Задать вопрос
AterCattus
@AterCattus
Люблю быстрый backend

[Решено] Есть ли в C++ возможность описать шаблонный метод?

Интересует возможность реализовать что-то вроде такого:
MyClass *inst = new MyClass();
char c = inst->get<char>();
long l = inst->get<long>();


Все, что пришло в голову, это что-то вида:
class MyClass {
    public:
        template <typename T>
        T get();
};

template <typename T>
T MyClass::get() {
    T val;
    .....
    return val;
}

MyClass *tf = new MyClass();
tf->get<dword>();

Но g++ на это ругается:
>> undefined reference to `unsigned int MyClass::get()'

P.S. Я не C++ программист, так что просьба сильно не глумиться.
P.P.S. Предварительно гуглил.
  • Вопрос задан
  • 7048 просмотров
Подписаться 8 Оценить Комментировать
Решения вопроса 1
Не проверял, но по-моему так должно сработать

class MyClass {
    public:
        template <typename T>
        T get();
};

template <typename T>
T MyClass::get() {
    T val;
    val = 42;
    return val;
}

template <>
char* MyClass::get<char *>() {
    return "foo";
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
Serrega
@Serrega
У вас проблема с созданием объекта. Сами функции описаны абсолютно правильно.
Так все заработает:
class MyClass {
    public:
        template <typename T> T get();
};

template <typename T>
T MyClass::get() {
    T val;
    return val;
}

int main() {
	MyClass tf;
	tf.get<int>();
	tf.get<long>();
	return 0;
}
Ответ написан
Комментировать
AterCattus
@AterCattus Автор вопроса
Люблю быстрый backend
Оказалось, что проблема в том, что реализацию метода я описал в cpp файле, а должен был в том же h. Внес внутрь — заработало. И с инстанцированием проблем нет, отлично отрабатывает:
    MyClass *tf = new MyClass();
    printf( "i=%d\n", tf->get<int>() );
    printf( "f=%f\n", tf->get<double>() );

# 
i=42
f=42.000000


Но тут возникла другая проблема. А как описать реализацию шаблона для конкретного типа?
tf->get<char*>()


Вот так не работает:
class MyClass {
    public:
        char* get();

        template <typename T>
        T get();
};

template <typename T>
T MyClass::get() {
    T val;
    val = 42;
    return val;
}

char* MyClass::get() {
    return "foo";
}



>>In member function ‘T MyClass::get() [with T = char*]’:
>> instantiated from here // tf->get<char*>()
>> error: invalid conversion from ‘int’ to ‘char*’ // val = 42;
Ответ написан
AterCattus
@AterCattus Автор вопроса
Люблю быстрый backend
Кстати, может кому пригодится. У меня gcc 4.6.3 в -O2 выкидывает реализацию шаблона для конкретного типа, т.е. в итоговый бинарник реализация template <> char* MyClass::get<char *>() не попадает. Получаю segfault при выполнении.
В -O1 уже все ок.

Баг это или фича, хз.
Ответ написан
AterCattus
@AterCattus Автор вопроса
Люблю быстрый backend
Как это выглядит:
TypedFile *tf = new TypedFile(fd);
int i = tf->read<int>();
char* str = tf->read<char*>();
printf("addr:%X\n", (size_t)str);
printf("value:%s\n", str);


-g:
addr:1167290
value: Михххх

-O2:
addr:D09CD008
Segmentation fault

Посмотрел что в итоге попадает в оптимизированную версию (objdump -d ). Реализация для char* в файле есть, но вот в месте вызова развернуто в два вызова общего варианта: ожидаемый get<int> и get<intptr_t> транслируемый в общий вариант T get<T> вместо char* get<char*>.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы