Compilation fails if specific specialization is used

Is it possible to specialize a template in a way that results in a compile-time error when creating that specialization? For example, I have a class that int

doesn't make sense as a type:

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
}

      

Is this possible somehow (ideally with a meaningful error message)?

+3


source to share


4 answers


If you want to customize error messages and can use C ++ 11, you can move on to the new one 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

I thought I could explain one thing. Of course, it is possible to cause an error message to this specialization, either static_assert

, enable_if

or without specifying the function (this is provided by the three answers). But I don't know how to force the error for this specialization.

The methods static_assert

and enable_if

are subject to SFINAE, so you won't get an error if someone later adds this function to the class Careful

:

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

      



(I think this is good, but it is still worth noting). Likewise, the code template<> void Careful::f(int value);

is just a declaration for this specialization f

- later someone can add a definition for it.

Edit 2

Yes this question answers, but I thought I should follow the most direct approach (and IMO, the "correct" approach): use 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

works like @ hmjd's method not defining a function, but it explicitly states that no one can provide a function implementation. Also, the compiler message will be descriptive (note that this is a compiler error, not a linker error, so it is probably easier to find the source of the error). In g ++, the error message for using the delete

d function reads error: use of deleted function โ€˜void Careful::f(T) [with T = int]โ€™

. And if someone later tries to define the function elsewhere, they will end up with an error redefinition of โ€˜void Careful::f(T) [with T = int]โ€™

, not an error at all.

+4


source


You can use boost :: enable_if to generate a compile time error when a template is specialized for a specific type



+3


source


Declaring a specialization but not providing a definition will result in an error:

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

      

+2


source


You can at least make the connection fail. Just don't do a function like (s), which doesn't make sense:

#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
}

      

with my g ++, I get this error in the linking step:

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

      

This is not a customized message, but the link is broken.

+1


source







All Articles