скрыть шаблон функции, объявить специализации - PullRequest
2 голосов
/ 28 января 2010

Это продолжение шаблонов C ++: предотвращение создания базового шаблона

Я использую шаблоны для достижения перегрузки функций без путаницы неявных преобразований типов: объявляю шаблон функции, определяю нужные специализации (перегрузки). все хорошо, кроме неправильного кода не выдает ошибок до фазы соединения:

lib.hpp:

template<class T> T f(T v);

lib.cpp:

#include "lib.hpp"

template<> long f(long v) { return -v; }
template<> bool f(bool v) { return !v; }

main.cpp:

#include <iostream>
#include "lib.hpp"

int main()
{
    std::cout
        << f(123L) << ", "
        << f(true) << ", "
        << f(234) << "\n"
    ;
}

вывод gcc:

c++ -O2 -pipe -c main.cpp
c++ -O2 -pipe -c lib.cpp
c++ main.o lib.o -o main
main.o(.text+0x94): In function `main':
: undefined reference to `int get<int>(int)'

Я бы хотел, чтобы он не работал во время компиляции main.cpp. Можно ли как-то объявить только фактически реализованные специализации?

Какие у меня варианты? Цель - C ++ 03, и я в основном заинтересован в gcc-4.x и VC9.

Ответы [ 4 ]

5 голосов
/ 28 января 2010

Кажется, что выдает ошибку компоновщика, даже если вы не поместите его в отдельный файл.

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

#include <boost/static_assert.hpp>

template <class T> T f(T)
{
    //assert some type-dependent "always-false" condition,
    //so it won't be triggered unless this function is instantiated
    BOOST_STATIC_ASSERT(sizeof(T) == 0 && "Only long or bool are available");
}

template<> long f(long v) { return -v; }
template<> bool f(bool v) { return !v; }

int main()
{
    //f(100);
    f(100L);
    f(false);
}

И просто для общей информации, C ++ 0x имеет гораздо более элегантный способ справиться с этим:

template <class T> T f(T) = delete;

template<> long f(long v) { return -v; }
template<> bool f(bool v) { return !v; }
1 голос
/ 23 января 2011

Лучший способ - реализовать этот базовый шаблон с помощью чего-то недопустимого (не нелегального) кода C ++. Например,

template<class T> T f(T v) { return v.Default_Implementation_Not_Available; }

Эта ошибка будет временем компиляции; и он генерируется только тогда, когда вы создаете инстанцию ​​любой версии, кроме 'long' и 'bool'. Если вы не создадите экземпляр версии 'int', компиляция пройдет хорошо.

0 голосов
/ 28 января 2010

При компиляции main.cpp у компилятора нет возможности узнать, какие специализации шаблонов могут существовать в каком-либо другом модуле компиляции - поэтому нет способа пометить эту ошибку во время компиляции, вам придется подождать до времени ссылки.

0 голосов
/ 28 января 2010

Я не верю, что можно делать то, что ты хочешь.См. Эти часто задаваемые вопросы для получения дополнительной информации:

Как я могу избежать ошибок компоновщика с моими функциями шаблона?

Как я могу избежать ошибок компоновщика с моими классами шаблона?

...