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)?
source to share
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.
source to share
You can use boost :: enable_if to generate a compile time error when a template is specialized for a specific type
source to share
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.
source to share