It is possible to check for the existence of class member functions. An implementation of the check could be taken from this answer: https://stackoverflow.com/a/257382/2492801.
Now a static_assert
can be used to ensure that a certain class has an implementation of a needed method. But if the class is templated, I do not know whether such a static assertion is possible or how to do it - except if I do the static_assert
for a concrete template parameter selection. The latter is possible, but it feels wrong...
Please consider the following code:
#include <iostream>
// SFINAE test
template <typename T>
class has_helloworld
{
typedef char one;
struct two
{
char x[2];
};
template <typename C>
static one test(decltype(&C::helloworld));
template <typename C>
static two test(...);
public:
enum
{
value = sizeof(test<T>(0)) == sizeof(char)
};
};
template <int number>
struct Hello
{
int helloworld()
{
return 0;
}
// The next line is not possible since class Hello is not complete yet.
// static_assert(has_helloworld<Hello<number>>::value);
};
template <int number>
struct Generic
{
};
int main()
{
// This is possible, but I don't like it
static_assert(has_helloworld<Hello<3>>::value);
// The next two lines are not possible because a template declaration cannot appear at block scope.
// template <int number>
// static_assert(has_helloworld<Hello<number>>::value);
std::cout << has_helloworld<Hello<2>>::value << std::endl;
std::cout << has_helloworld<Generic<2>>::value << std::endl;
return 0;
}
Here is a Godbolt link: https://godbolt.org/z/c3bKKMxcc
Is there a possibility in C++ to do a "templated static assert", so a static_assert
where I check a property of a class that depends on a template parameter without choosing a dummy value for that parameter?
Clarification: In my case in practice the template parameter does not play a role, it just impedes the static_assert
. So like in the code example, all template structs Hello
have the required method regardless of the parameter number
.
Template classes are not classes.
Template classes generate classes.
Asking if a template class has a specific member is a category error. It is like asking if a specific type of paper has mountains drawn on it.
You might say "but I know that this paper is always used to draw maps of the rockies!" C++ doesn't know this, it just knows you are talking about paper.
The mapping of template class plus parameters to class is a Turing complete computation. This process cannot be inverted in the general case - for a template class X<A>
, you cannot answer the question "what properties does X<>
have for an arbitrary A
".
When designing the template system for C++, the computational model chosen was too strong to be inverted like that.
It is true that the most typical use of templates uses a far weaker set of computational capabilities - most uses of templates are a step removed from macros with basic meta type checking.
As a concrete example, a template class can be written such that Hello<N>
has a specific property if and only if the Collatz conjecture is true for the constant N
, and it accepts bignums as arguments.
In order to know the properties of Hello<?>
for an arbitrary argument, the compiler would have to prove the Collatz conjecture.
Now, you might say, "I'm not doing that". Too bad; C++ doesn't say "so long as the person writing the template doesn't do anything fancy, you can invert the template mapping and solves this problem".
It could; it could define a weaker set of template mechanics that can be safely inverted without hitting this problem. A number of languages do exactly that (Generics in Java, which both weaken the kind of mapping you can do and have a rather different implementation; C#'s version is a bit stronger than Java, but also weakens C++ templates in a somewhat similar way).