I am trying to get static_assert to help me avoid null pointers in C++11.
The problem seems to be that C++11 require the compiler to compile templates even if they are not instantiated.
I have the following code:
#include <type_traits>
template<typename T, typename... Us>
std::enable_if_t< std::is_constructible<T, Us...>::value == true, T * >
create_if_constructible(Us... args) { return new T(args...); }
template<typename T, typename... Us>
std::enable_if_t< std::is_constructible<T, Us...>::value == false, T * >
create_if_constructible(Us... args) {
static_assert( false, "Class T constructor does not match argument list.");
return nullptr;
}
struct ClassA {
ClassA(int a, string b) {}
};
void foo() {
ClassA *a = create_if_constructible<ClassA>(1, "Hello");
// ClassA *b = create_if_constructible<ClassA>(1, "Hello", "world"); // I want compile time error here.
}
I would like this to compile without error. But the static_assert is compiled and gives me a compile time error.
Only if the the second instantiation of the ClassA is in the code should it give me a compile time error.
The standard permits, but does not require, compilers to diagnose templates for which no valid instantiation can be generated. This can range from simple syntax errors to your example of a constant false expression in a static_assert. §14.6 [temp.res]/p8:
If no valid specialization can be generated for a template, and that
template is not instantiated, the template is ill-formed, no
diagnostic required.
I'm rather baffled by all this SFINAE machinery, though. A simple
template<typename T, typename... Us>
T* create_if_constructible(Us... args) { return new T(args...); }
already refuses to compile if T is not constructible from the parameter given, so I'm not sure how this complex circumlocution will help you "avoid null pointers".
Regardless, a simple way to make choosing the second function template a compile-time error is to explicitly delete it.
template<typename T, typename... Us>
std::enable_if_t< std::is_constructible<T, Us...>::value == false, T * >
create_if_constructible(Us... args) = delete;
Alternatively, if you are partial to static_asserts, perhaps because of the custom error message, you must ensure that there is theoretically a way to generate a valid instantiation of your template. That means that 1) what you are static_asserting on must depend on a template argument, and 2) there must be theoretically a way for the condition to be true. A simple way is to use an auxiliary template:
template<class> class always_false : std::false_type {};
template<typename T, typename... Us>
std::enable_if_t< std::is_constructible<T, Us...>::value == false, T * >
create_if_constructible(Us... args) {
static_assert( always_false<T>::value, "Class T constructor does not match argument list.");
return nullptr;
}
The key point here is that the compiler cannot assume that always_false<T>::value is always false because it is always possible that there's a specialization later that sets it to true, and so it is not allowed to reject this at template definition time.
In all C++ standards ever, templates are compiled in two phases. The second phase is instantiation, but compilation can also fail in phase 1. In particular, syntax errors are detected in phase 1.
In your case, the simpler solution is to leave out the body of the second instantiation.
Another solution is to use T in the static_assert, so the compiler must delay evaluation to phase 2. Trivially: static_assert(sizeof(T)==0,
Related
Edit: This funcion have to check types one by one and return obj of any that will satisfy condition or nullptr.
template <typename... Args, typename = std::enable_if_t<(sizeof...(Args) == 0)>()>
std::nullptr_t f() { return nullptr; }
template <typename T, typename... Args>
BaseClassOfAllArgs* f() {
if (<some condition related to T...>)
return new T;
return f<Args...>();
}
This code works for me. But I wonder if is it possible to rewrite this code to use concept?
I mean something like this:
template <typename... Args>
concept NoArgs = (sizeof...(Args) == 0);
and then use it instead of std::enable_if(this code doesnt work)
template <NoArgs Args>
std::nullptr_t f() { return nullptr; }
template <typename T, typename... Args>
BaseClassOfAllArgs* f() {
if (<some condition related to T...>)
return new T;
return f<Args...>();
}
EDIT: Here is working example of code after taking some tips from
guys in comments. After I added 'Base' to the template it turns out that EmptyPack concept is no longer needed. And First template naturally needs 3 typenames. However, I am not sure about this concept EmptyPack. Is it really making my program ill-formed no diagnostic required?
#include <iostream>
#include <type_traits>
#include <typeinfo>
class X {};
class A : public X {};
class B : public X {};
class C : public X {};
class D : public C {};
class E {};
template<class T, class... Args >
concept DerivedsOfBase = (std::is_base_of_v<T, Args> && ...);
template<typename... Args>
concept EmptyPack = sizeof...(Args) == 0;
template<typename T>
std::nullptr_t f() {
std::cout << "End of the types list" << std::endl;
return nullptr;
}
template<typename Base, typename T, typename... Args> requires DerivedsOfBase<Base, T, Args...>
Base* f() {
std::cout << typeid(T).name() << std::endl;
if (<some condition related to T>)
return new T;
return f<Base, Args...>();
}
int main()
{
auto ptr = f<X, A, B, C>();
auto ptr2 = f<X, A, B, D>();
//auto ptr3 = f<X, A, B, E>(); // compile error
return 0;
}
Any template parameter pack that only has valid instantiations for packs of size 0 makes your program ill-formed, no diagnostic required.
This applies to your first "working" example, as well as any practical variant I can think of using concepts.
From the N3690 draft standard [temp.res] 14.6/8:
If every valid specialization of a variadic template requires an empty template parameter pack, the template is ill-formed, no diagnostic required.
(I've seen that in many versions of C++, I'm just using a random draft standard as it showed up when I googled C++ standard pdf.)
Note that (a) your two f are overloads not specializations, and (b) what C++ programmers mean by "valid specialization of a template" and what the standard means are not quite the same thing.
In essence, pretty much any attempt at your concept will result in ill-formed, no diagnostic required programs.
To see the problem here, we'll reword the standard using negation:
If (every valid specialization of a variadic template requires an empty template parameter pack) then (the template is ill-formed, no diagnostic required).
We can convert this "forall" into a "there exists". "Forall X, P(X)" is the same as "Not( There exists X, Not P(X) )".
Unless (there exists a valid specialization of a variadic template with a non-empty template parameter pack) then (the template is ill-formed, no diagnostic required).
If a variadic template has a requires clause that mandates the variadic template pack is empty, then no valid specialization of that template with an empty parameter pack exists. So your template is ill-formed, no diagnostic required.
In general, these kind of rules exist so that compilers can check if your code would always be nonsense. Things like templates where no type parameter could make it compile, or packs that must be empty, are generally a sign that your code has bugs. By making it ill-formed and not requiring a diagnostic, compilers are permitted to emit diagnostics and fail to compile.
An issue I have with the standard is that it is not just permitted to fail to compile, but it is permitted to compile a program that does literally anything.
Because the compiler is permitted to do this, and some optimizations in other cases actually result in this happening, you should avoid writing code that is ill-formed, no diagnostic required, like the plague.
A workaround is:
namespace implementation_details {
struct never_use_me;
}
template <class=implementation_details::never_use_me>
std::nullptr_t f() { return nullptr; }
template <typename T, typename... Args>
T* f() {
if (<some condition related to T...>)
return new T;
return f<Args...>();
}
another option is:
template <typename T, typename... Args>
T* f() {
if (<some condition related to T...>)
return new T;
if constexpr (sizeof...(Args)==0)
return nullptr;
else
return f<Args...>();
}
You don't really need concepts for that, simply use if constexpr:
T* f() {
if constexpr (sizeof...(Args) != 0) {
if (<some condition related to T...>)
return new T;
return f<Args...>();
} else {
return nullptr;
}
}
If you really want separated functions, you could always use overloading:
template <typename T> // no pack
T* f() {
return nullptr;
}
template <typename T, typename Arg1, typename... Args> // one of more Args
T* f() {
if (<some condition related to T...>)
return new T;
return f<Arg1, Args...>();
}
But of course you can always use requires expressions if you really want to keep the same logic you had with SFINAE. It should be possible (and enough) without a declared concept, but only with constraint:
template <typename T, typename...> // pack logically always empty
T* f() {
return nullptr;
}
template <typename T, typename... Args> requires (sizeof...(Args) > 0)
T* f() {
if (<some condition related to T...>)
return new T;
return f<Args...>();
}
Of course you can also wrap the condition inside a concept, but you gain very little using this technique in this case, since you still have to use the concept inside a require clause:
template<typename... Args>
concept nonempty_pack = sizeof...(Args) > 0;
template <typename T, typename...> // pack logically always empty
T* f() {
return nullptr;
}
template <typename T, typename... Args> requires nonempty_pack<Args...>
T* f() {
if (<some condition related to T...>)
return new T;
return f<Args...>();
}
The syntax template<my_concept T> will send T as the first parameter. You'll always get that parameter snet automatically, hence the need to put the concept in the requires clause.
Since C++20 concepts aren't standardized yet, I'm using static_assert as a makeshift concept check, to provide helpful error messages if a type requirement isn't met. In this particular case, I have a function which requires that a type is callable before getting its result type:
template <typename F, typename... Args>
void example() {
static_assert(std::is_invocable_v<F, Args...>, "Function must be callable");
using R = std::invoke_result_t<F, Args...>;
// ...
}
In addition, I require that the callable's result must be some kind of std::optional, but I don't know what type the optional will hold, so I need to get that type from it:
using R = // ...
using T = typename R::value_type; // std::optional defines a value_type
However, this will fail if type R doesn't have a value_type, e.g. if it's not a std::optional as expected. I'd like to have a static_assert to check for that first, with another nice error message if the assertion fails.
I could check for an exact type with something like std::is_same_v, but in this case I don't know the exact type. I want to check that R is some instance of std::optional, without specifying which instance it must be.
One way to do that is with a helper trait:
template <typename T>
struct is_optional { static constexpr bool value = false; };
template <typename T>
struct is_optional<std::optional<T>> { static constexpr bool value = true; };
template <typename T>
constexpr bool is_optional_v = is_optional<T>::value;
…and then I can write:
static_assert(is_optional_v<R>, "Function's result must be an optional");
That works, but it seems a little awkward to pollute my namespace with a helper trait just for a one-off check like this. I don't expect to need is_optional anywhere else, though I can imagine possibly ending up with other one-off traits like is_variant or is_pair too.
So I'm wondering: is there a more concise way to do this? Can I do the pattern matching on instances of std::optional without having to define the is_optional trait and its partial specialization?
Following the suggestion by several respondents, I made a re-usable trait:
template <typename T, template <typename...> typename Tpl>
struct is_template_instance : std::false_type { };
template <template <typename...> typename Tpl, typename... Args>
struct is_template_instance<Tpl<Args...>, Tpl> : std::true_type { };
template <typename T, template <typename...> typename Tpl>
constexpr bool is_template_instance_v = is_template_instance<T, Tpl>::value;
…so that I can write:
static_assert(is_template_instance_v<R, std::optional>, "Function's result must be an optional");
This is just as many lines and declarations as the is_optional trait, but it's no longer a one-off; I can use the same trait for checking other kinds of templates (like variants and pairs). So now it feels like a useful addition to my project instead of a kluge.
Can I do the pattern matching on instances of std::optional without having to define the is_optional trait and its partial specialization?
Maybe using implicit deduction guides for std::optional?
I mean... something as
using S = decltype(std::optional{std::declval<R>()});
static_assert( std::is_same_v<R, S>, "R isn't a std::optional" );
Explanation.
When R is std::optional<T> for some T type, std::optional{r} (for an r value of type R) should call the copy constructor and the resulting value should be of the same type R.
Otherwise, the type should be different (std::optional<R>).
The following is a full compiling example.
#include <iostream>
#include <optional>
template <typename T>
bool isOptional ()
{
using U = decltype(std::optional{std::declval<T>()});
return std::is_same_v<T, U>;
}
int main ()
{
std::cout << isOptional<int>() << std::endl; // print 0
std::cout << isOptional<std::optional<int>>() << std::endl; // print 1
}
Anyway, I support the suggestion by super: create a more generic type-traits that receive std::option as template-template argument.
template<typename T, size_t M, size_t K, size_t N, typename std::enable_if_t<std::is_floating_point<T>::value, T> = 0>
void fastor2d(){//...}
I copied this line of code from cpp-reference(only the std::enable_if part, i do need T and all three of the size_t's), because i would like to use this function only when floating_types are used on it ... it does not compile.
Could somebody explain to me, why, and what it even does? While i am at it, how do you call this function afterwards?
Every tutorial or question here on SO gets bombed with answers, and that is great, but to someone who does not understand jacks*** of what is happening, even those are not really helpful.(sry, if possibly slightly agitated or aggressive)
EDIT: i greatly appreciate all answers as of now, i realize that my wording might have been a bit off ... i understand what a template parameter is, and know the difference between runtime and compiletime etc, but i just cant get a good grasp of the syntax behind std::enable_if
EDIT2:
template<typename T, size_t M, size_t K, size_t N, typename = std::enable_if_t<std::is_integral<T>::value>>
void fastor2d(){
Fastor::Tensor<T,M,K> A; A.randInt();
}
This is literally the only thing i need changed. Notice the random() part
template<typename T, size_t M, size_t K, size_t N, typename = std::enable_if_t<std::is_floating_point<T>::value>>
void fastor2d(){
Fastor::Tensor<T,M,K> A; A.random();
}
I'll try to explain this as simple as possible not to go into the language details too much since you asked for it.
Template arguments are compile time arguments (they do not change during the run-time of your application). Function arguments are run-time and have a memory address.
Calling this function would look something like this:
fastor2d<Object, 1, 2, 3>();
In the <> brackets you see the compile-time arguments or more accurately the template parameters, and the function in this case takes 0 runtime arguments in the () brackets. The last compile time argument has a default argument which is used to check whether the function should compile at all (enable_if type). If you want to know more clearly what enable if does you should search for the term SFINAE, which is a template metaprogramming technique used to determine whether a function or class should exist or not.
Here is a short SFINAE example:
template<typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>>
void function(T arg)
{
}
function(0.3f); //OK
function(0.0); //OK double results in std::is_floating_point<double>::value == true
function("Hello"); //Does not exist (T is not floating point)
The reason the third function call fails, is because the function does not exist. This is because the enable if caused the function not to exist when the compile-time bool that is passed in as its' template argument is false.
std::is_floating_point<std::string>::value == false
Do note that a lot of people agree that the SFINAE syntax is horrible and that a lot of SFINAE code will not be necessary anymore with the introduction of concepts and constraints in C++ 20.
Rather than a top-down approach starting with you code snippet, I'll take a bottom-up approach to explain some important details about templates and what tools and techniques are involved.
At heart, templates are a tool that let you write C++ code that applies to a range of possible types, not strictly for a fixed type. In a statically-typed language, this is firstly a great tool for reusing code without sacrificing type safety, but in C++ in particular, templates are very powerful because they can be specialized.
Every template declaration begins with the keyword template, and a list of type or non-type (i.e value) parameters. Type parameters use the special keyword typename or class, and are used to let your code work over a range of types. Non-type parameters simply use the name of an existing type, and these let you apply your code to a range of values that are known at compile-time.
A very basic templated function might look like the following:
template<typename T> // declare a template accepting a single type T
void print(T t){ // print accepts a T and returns void
std::cout << t; // we can't know what this means until the point where T is known
}
This lets us reuse code safely for a range of possible types, and we can use it as follows:
int i = 3;
double d = 3.14159;
std::string s = "Hello, world!";
print<int>(i);
print<double>(d);
print<std::string>(s);
The compiler is even smart enough to deduce the template parameter T for each of these, so you can safely get away with the following, functionally identical code:
print(i);
print(d);
print(s);
But suppose you want print to behave differently for one type. Suppose, for example, you have a custom Point2D class that needs special handling. You can do this with a template specialization:
template<> // this begins a (full) template specialization
void print<Point2D>(Point2D p){ // we are specializing the existing template print with T=Point2D
std::cout << '(' << p.x << ',' << p.y << ')';
}
Now, anytime we use print with T=Point2D, the specialization is chosen. This is really useful, for example, if the generic template just doesn't make sense for one specific type.
std::string s = "hello";
Point2D p {0.5, 2.7};
print(s); // > hello
print(p); // > (0.5,2.7)
But what if we want to specialize a template for many types at once, based on a simple condition? This is where things become a little meta. First, let's try to express a condition in a way that lets them be used inside templates. This can be a little tricky because we need compile-time answers.
The condition here will be that T is a floating point number, which is true if T=float or T=double and false otherwise. This is actually fairly simple to achieve with template specialization alone.
// the default implementation of is_floating_point<T> has a static member that is always false
template<typename T>
struct is_floating_point {
static constexpr bool value = false;
};
// the specialization is_floating_point<float> has a static member that is always true
template<>
struct is_floating_point<float> {
static constexpr bool value = true;
};
// the specialization is_floating_point<double> has a static member that is always true
template<>
struct is_floating_point<double> {
static constexpr bool value = true;
}
Now, we can query any type to see if it's a floating point number:
is_floating_point<std::string>::value == false;
is_floating_point<int>::value == false;
is_floating_point<float>::value == true;
is_floating_point<double>::value == true;
But how can we use this compile-time condition inside another template? How can we tell the compiler which template to choose when there are many possible template specializations to choose from?
This is achieved by taking advantage of a C++ rule called SFINAE, which in basic English, says, "when there are many possible template specializations to choose from, and the current one doesn't make sense*, just skip it and try the next one."
There's a list of errors, when attempting to substitute template arguments into templated code, that cause the template to be ignored without an immediate compiler error. The list is a bit long and complex.
One possible way that a template doesn't make sense is if it tries to use a type that doesn't exist.
template<typename T>
void foo(typename T::nested_type x); // SFINAE error if T does not contain nested_type
This is the exact same trick that std::enable_if uses under the hood. enable_if is a template class accepting a type T and a bool condition, and it contains a nested type type equal to T only when the condition is true. This is also pretty easy to achieve:
template<bool condition, typename T>
struct enable_if {
// no nested type!
};
template<typename T> // partial specialization for condition=true but any T
struct enable_if<true, T> {
typedef T type; // only exists when condition=true
};
Now we have a helper that we can use in place of any type. If the condition we pass is true, then we can safely use the nested type. If the condition we pass is false, then the template is no longer considered.
template<typename T>
typename std::enable_if<std::is_floating_point<T>::value, void>::type // This is the return type!
numberFunction(T t){
std::cout << "T is a floating point";
}
template<typename T>
typename std::enable_if<!std::is_floating_point<T>::value, void>::type
numberFunction(T t){
std::cout << "T is not a floating point";
}
I completely agree that std::enable_if<std::is_floating_point<T>::value, void>::type is a messy way to spell out a type. You can read it as "void if T is floating point, and otherwise stop and try the next overload"
Finally, to take apart your example:
// we are declaring a template
template<
typename T, // that accepts some type T,
size_t M, // a size_t M,
size_t K, // a size_t K,
size_t N, // a size_t N,
// and an unnamed non-type that only makes sense when T is a floating point
typename std::enable_if_t<std::is_floating_point<T>::value, T> = 0
>
void fastor2d(){//...}
Note the = 0 at the end. That's simply a default value for the final template parameter, and it lets you get away with specifying T, M, K, and N but not the fifth parameter. The enable_if used here means that you can provide other templates called fastor2d, with their own sets of conditions.
First of all, I'll rewrite your function in a working form
template <typename T, size_t M, size_t K, size_t N,
std::enable_if_t<std::is_floating_point<T>::value, int> = 0>
void fastor2d() // ..........................................^^^ int, not T
{ }
The point is that I've changed the second template argument of std::enable_if_t form T to int.
I've also removed the typename before std::enable_if_t but isn't important: the typename is implicit in the _t at the end of std::enable_if_t, introduced from C++14. In C++11 the correct form is
// C++11 version
typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0
// ^^^^^^^^ no _t ^^^^^^
But why it works?
Start from the name: SFINAE.
Is a short form for "Substitution Failure Is Not An Error".
It's a C++ rule so that when you write some thing as
template <int I, std::enable_if_t< I == 3, int> = 0>
void foo ()
{ }
and I is 3, the condition of std::enable_if_t is true so std::enable_if_t< I == 3, int> is substituted with int so foo() is enabled but when I isn't 3, the condition of std::enable_if_t if false so std::enable_if_t< I == 3, int> is not substituted so foo() isn't enabled but this ins't an error (if, through overloading, there is another foo() function, enabled, that matches the call, obviously).
So where is the problem in your code?
The problem is that std::enable_if_t is substituted, when the first template parameter is true, with the second parameter.
So if you write
std::enable_if_t<std::is_floating_point<T>::value, T> = 0
and you call
fastor2d<float, 0u, 1u, 2u>();
the std::is_floating_point<float>::value (but you can also use the shorter form std::is_floating_point_v<T> (_v and not ::value)) so the substitution take place and you get
float = 0
but, unfortunately, a template value (not type) parameter can't be of type floating point, so you get an error.
If you use int instead of T, the substitution give you
int = 0
and this is correct.
Another solution can be use the following form
typename = std::enable_if_t<std::is_floating_point<T>::value, T>
as suggested by Andreas Loanjoe, because the substitution give you
typename = float
that is a valid syntax.
But this solution has the drawback that doesn't works when you want to write two alternative functions, as in the following example
// the following solution doesn't works
template <typename T,
typename = std::enable_if_t<true == std::is_floating_point<T>::value, int>>
void foo ()
{ }
template <typename T,
typename = std::enable_if_t<false == std::is_floating_point<T>::value, int>>
void foo ()
{ }
where works the solution based on the value
// the following works
template <typename T,
std::enable_if_t<true == std::is_floating_point<T>::value, int> = 0>
void foo ()
{ }
template <typename T,
std::enable_if_t<false == std::is_floating_point<T>::value, int> = 0>
void foo ()
{ }
I was wondering if something as unit testing template was a thing. Let me explain my needs.
I have a highly templated library. I have a lot of sfinae type traits, and some static_assert.
What I want to test is the validity of sfinae type traits, and test if my static_assert are throwing the right thing. Knowing what is my coverage would be awesome.
Here's an example of what my code look like:
template<typename T>
using false_v = !std::is_same<T, T>::value;
// Here are my types traits
template<typename T, typename... Args>
struct SomeCondition1 { /* ... */ };
template<typename T, typename... Args>
struct SomeCondition2 { /* ... */ };
// This is a master type trait, that test every others
template<typename T, typename... Args>
using Conditions = std::integral_constant<bool,
SomeCondition1<T, Args...>::value && SomeCondition2<T, Args...>::value
>;
// This is the function that is call when everything is okay.
template<typename T, typename... Args,
std::enable_if_t<Conditions<T, Args...>::value, int> = 0>
void doThing(Args...) {}
// These function are called only to trigger
// static asserts to give the user a diagnostic to explain what's wrong.
template<typename T, typename... Args,
std::enable_if_t<SomeCondition1<T, Args...>::value && !SomeCondition2<T, Args...>::value, int> = 0>
void doThing(Args...) {
static_assert(false_v<T>, "Error, SomeCondition2 not met");
}
template<typename T, typename... Args,
std::enable_if_t<!SomeCondition1<T, Args...>::value && SomeCondition2<T, Args...>::value, int> = 0>
void doThing(Args...) {
static_assert(false_v<T>, "Error, SomeCondition1 not met");
}
template<typename T, typename... Args,
std::enable_if_t<!SomeCondition1<T, Args...>::value && !SomeCondition2<T, Args...>::value, int> = 0>
void doThing(Args...) {
static_assert(false_v<T>, "Error, both conditions not met");
}
I was thinking about testing if the traits were ok, and if the right static assert is thrown for my cases. If the wrong static assert is triggered, that's a bug, and I would like to be able to test it. Trying to cover all cases for all compilers and check every message by hand is really time consuming and error prone.
The problem of unit-testing template code for ranges of argument types is
fairly well addressed by googletest
with its TYPED TESTS feature
and Type-Parameterized Tests
feature.
A limitation of these features is that they are only immediately applicable to testing
templates with just one parameter. But it's not difficult to work around this limitation:
see this question and the accepted answer.
None of that helps, however, with the further problem of testing the correctness static_asserts in
template code. The special obstacle for that kind of testing, of course, is that
a static_assert fires by compilation failure; so if it fires, correctly or otherwise,
there is nothing you can execute to show that it does.
This bothered me too several years ago. I posted How to write runnable tests of static_assert? and also wrote the only answer so far
received (lately updated for C++14 and current compilers).
Combining these resources and techniques should yield the solution you're looking for.
Can I specify exactly what kind of arguments a template can receive? For example, I'd like to create a template that can only be instantiated with classes that are or extend class A. In Java, generics support this with:
class B<T extends A> { }
Can something similar be achieved with templates in C++?
template <typename T (?)> class B { }
There are two ways to do this.
First, through a hidden dummy template parameter that uses std::enable_if with a std::is_base_of<A, T>::value as condition. If the latter expression evaulates to false, then the nested type does not exist in std::enable_if. If you were using this on overloaded functions, SFINAE then means "substitution failure is not an error", and the overload in question would be removed from the set of viable functions. HOwever in this situation, there is no other class template to match your call, and then you do get a compile-time error.
SFINAE is a very subtle mechanism and easy to get wrong. E.g. if you have multiple class specializations with different SFINAE conditions, you have to make sure that they are all non-overlapping, or else you get an ambiguity.
Second, you can do a simple static_assert with a std::is_base_of<A,T>::value inside the body of the class. The advantage of this method is that you also specify a more readable error message compared to the SFINAE method. A disadvantage is that you always get an error, and you cannot silently suppress this particular template and select another one. But overall I think this method is recommended in your case.
#include<type_traits>
class A {};
class C: public A {};
class D {};
// first alternative: SFINAE on hidden template parameter
template
<
typename T,
typename /* dummy */ = typename std::enable_if<
std::is_base_of<A, T>::value
>::type
>
class B
{
};
// second alternative: static_assert inside class
template
<
typename T
>
class E
{
static_assert(std::is_base_of<A, T>::value, "A should be a base of T");
};
int main()
{
B<A> b1;
B<C> c1;
//B<D> d1; // uncomment this line to get a compile-time error
E<A> b2;
E<C> c2;
//E<D> d2; // uncomment this line to get a compile-time error
return 0;
}
As was pointed out in the comments, you can use either a decent C++11 compiler (VC++ 2010 or later, gcc 4.5 or later) or the Boost or TR1 libraries to get the <type_traits> functionality. Note however that the std::is_base_of<A, A>::value evaluates to true, but the old boost::is_base_of<A, A>::value used to evalute to false.
You can do this with static_assert and is_base_of:
#include <type_traits>
template<typename T> class D {
static_assert(std::is_base_of<A, T>::value, "must be derived from A");
};
Or you can use enable_if:
#include <type_traits>
template<typename T, typename = void> class D;
template<typename T> class D<T, typename std::enable_if<std::is_base_of<A, T>::value>::type> {
};
For C++03 you can use boost; is_base_of from Boost.TypeTraits, static_assert from Boost.StaticAssert, enable_if from Boost.EnableIf.