Сбой компиляции, если используется определенная специализация - PullRequest
3 голосов
/ 07 марта 2012

Можно ли специализировать шаблон таким образом, чтобы при создании этой специализации возникла ошибка компиляции? Например, у меня есть класс, для которого int s не имеет смысла как тип:

class Careful
{
    template <typename T>
    void f(T value) { std::cout << "Non-specialized version"; }
};

template <>
void Careful::f(double value)
{
    std::cout << "specialization for double";
}

template <>
void Careful::f(int value)
{
    // make this one fail to compile
}

Возможно ли это как-то (в идеале с осмысленным сообщением об ошибке)?

Ответы [ 4 ]

4 голосов
/ 07 марта 2012

Если вам нужны настраиваемые сообщения об ошибках и вы можете использовать C ++ 11, вы можете перейти на новый static_assert:

class Careful
{    
    template <typename T>
    void f(T value) {
        static_assert(std::is_same<T, int>::value, "Don't call f with an int!");
    }
};

EDIT

Я подумал, что могу объяснить одновещь.Конечно, возможно вызвать сообщение об ошибке для данной специализации, либо static_assert, enable_if, либо не определив функцию (это три ответа, которые были даны).Но я не знаю, как вызвать ошибку для данной специализации.

Методы static_assert и enable_if подчиняются SFINAE, поэтому вы не получитеошибка, если кто-то позже добавляет эту функцию в класс Careful:

void f(int value)
{
    std::cout << "Overloaded!" << std::endl;
}

(я думаю, что это хорошо, но все же стоит отметить).Точно так же код template<> void Careful::f(int value); является всего лишь предварительным объявлением для этой специализации f - позже кто-то может добавить определение для него.

Edit 2

Да, этот вопрос выглядит ответом,но я подумал, что должен следовать наиболее прямому подходу (и IMO, «правильному» подходу): использование delete.

class Careful
{
    template <typename T>
    void f(T value) { std::cout << "Non-specialized version"; }
};

template <>
void Careful::f(double value)
{
    std::cout << "specialization for double";
}

template <>
void Careful::f(int value) = delete;

delete работает как подход @ hmjd не определятьфункция, но она явно говорит, что никто не может обеспечить реализацию функции.Кроме того, сообщение компилятора будет описательным (обратите внимание, что это ошибка компилятора , а не ошибка linker , поэтому, вероятно, легче найти источник ошибки).На g ++ сообщение об ошибке при использовании функции delete d читается как error: use of deleted function ‘void Careful::f(T) [with T = int]’.И если позже кто-то попытается определить функцию в другом месте, он получит ошибку redefinition of ‘void Careful::f(T) [with T = int]’, а не ошибку вообще.

3 голосов
/ 07 марта 2012

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

2 голосов
/ 07 марта 2012

Объявление специализации, но не предоставление определения приведет к ошибке:

template <>
void Careful::f(int value);
1 голос
/ 07 марта 2012

Вы можете по крайней мере сделать ссылку неудачной Только не реализуйте функцию для типа (ов), это не имеет смысла:

#include <iostream>
using namespace std;

class Careful
{
public:
    template <typename T>
    void f(T value) { std::cout << "Non-specialized version"; }
};

template <>
void Careful::f(double value)
{
    std::cout << "specialization for double";
}

template <>
void Careful::f(int value); // int makes no sense. As long as you don't implement it for this type, compilation will fail at instantiation.

int main() {
    Careful x;
    x.f(3.14);
    x.f(42); // this will fail
}

с моим g ++, я получаю эту ошибку в шаге связывания:

 main.cpp:(.text+0x4b): undefined reference to `void Careful::f<int>(int)'

Это не настроенное сообщение, но соединение не удается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...