I want to ensure, that a derived class implements a specific static method. I think doing so should be possible using static_assert, std::is_same, decltype, CRTP and maybe making use of SFINAE. However, similar code I found so far is quite complex and it seems I do not yet fully understand it making me unable to adopt it to my needs.
What I tried so far is this
template <class T>
class Base
{
static_assert(std::is_same<decltype(T::foo(1)), int>::value, "ERROR STRING");
};
class Derived : public Base <Derived>
{
public:
static int foo(int i) { return 42; };
};
However, it does not compile telling me, that Derived does no have an element named foo even if the method is correctly implemented. Furthermore providing actual parameters for foo in the expression inside static_assert feels wrong.
Searching SO revealed a similar question which finally lead me to this piece of code where it is checked that a type has methods begin() and end() returning iterators. So I tried to adopt this code to my needs.
template <class T>
class Base
{
template<typename C>
static char(&g(typename std::enable_if<std::is_same<decltype(static_cast<int(C::*)(int)>(&C::foo)), int(C::*)(int)>::value, void>::type*))[1];
template<typename C>
static char(&g(...))[2];
static_assert(sizeof(g<T>(0)) == 1, "ERROR STRING");
};
But this code does not compile because the assertion fires.
So my questions are
- Why does the compiler cannot find Derived::foo in my first example?
- What exactly does
typename C::const_iterator(C::*)() const
in the example code mean? Isn't it a const function returning C::const_iterator and taking no arguments? What exactly doesC::*
mean? So why isint(C::*)(int)
then wrong in my case? - How to correctly solve my problem?
I'am using MSVC 12 but if possible the code should be portable.
See Question&Answers more detail:os