Reputation: 55826
I have a templated class
(call it Foo
) which has several specializations. I would like the compilation to fail if someone tries to use an unspecialized version of Foo
.
Here is what I actually have:
template <typename Type>
class Foo
{
Foo() { cannot_instantiate_an_unspecialized_Foo(); }
// This method is NEVER defined to prevent linking.
// Its name was chosen to provide a clear explanation why the compilation failed.
void cannot_instantiate_an_unspecialized_Foo();
};
template <>
class Foo<int>
{ };
template <>
class Foo<double>
{ };
So that:
int main()
{
Foo<int> foo;
}
Works while:
int main()
{
Foo<char> foo;
}
Does not.
Obviously, the compiler chain only complains when the linking process takes place. But is there a way to make it complain before ?
I can use boost
.
Upvotes: 45
Views: 8399
Reputation: 35469
A trick for C++0x (also available with a C++03 static_assert
emulation, but the error message isn't necessarily better than leaving the primary template undefined):
template<typename T>
struct dependent_false: std::false_type {};
template<typename Type>
struct Foo {
static_assert( dependent_false<Type>::value
, "Only specializations of Foo may be used" );
};
The assertion will only trigger when Foo
is instantiated with the primary template. Using static_assert( false, ... )
would trigger the assertion all the time.
Upvotes: 21
Reputation: 3873
Just don't define the class:
template <typename Type>
class Foo;
template <>
class Foo<int> { };
int main(int argc, char *argv[])
{
Foo<int> f; // Fine, Foo<int> exists
Foo<char> fc; // Error, incomplete type
return 0;
}
Why does this work? Simply because there isn't any generic template. Declared, yes, but not defined.
Upvotes: 55
Reputation: 477700
You can simply not define the base case:
template <typename> class Foo; // no definition!
template <> class Foo<int> { /* ... */ }; // Foo<int> is OK
Upvotes: 26