devoln
devoln

Reputation: 406

Propagate method staticness to derived class

template<typename T> struct Derived: T
{
  /*static*/ int foo(int x) { return T::foo(x) + 1; }
};

If T::foo(int x) is static then Derived<T>::foo(int x) should also be static. Otherwise Derived<T>::foo(int x) should be non-static.

Is there a way to let the compiler take care of this?

Upvotes: 1

Views: 160

Answers (2)

iammilind
iammilind

Reputation: 69988

Use below construct:

static_assert(std::is_same<decltype(&Derived::foo), decltype(&T::foo)>::value or
              (std::is_member_function_pointer<decltype(&Derived::foo)>::value and 
               std::is_member_function_pointer<decltype(&T::foo)>::value), 
              "Derived::foo & T::foo are not having same static-ness");

I have tested quickly with my g++ and it works fine.

What it does

  1. Takes address of both the methods and if they are comparable then they must be static. This means that the methods signatures are expected to be same (as implied in your example).
  2. If (1) fails then check if both the foo are function pointers of their respective classes types. Here no strictness of type, but you can impose with some more meta programming. Leaving up to you.

If both of above fails, then the compiler gives an error. This static_assert can be put within class Derived.

Notes: (1) If Derived::foo is static & T::foo is not then anyways, it gives error. (2) or & and are official keywords of C++. If certain compilers like MSVC doesn't support then use || & && respectively.

Upvotes: 0

Ami Tavory
Ami Tavory

Reputation: 76297

No, you cannot propagate staticness in the sense you ask. Incidentally, you could also ask the same thing about const:

int foo(int x) { return bar(x) + 1; } // Infer that foo is const because bar is

C++ specifiers are meant to convey intent about the interface, on which users can rely even if the implementation changes:

static int foo(x); // This method does not require an object
int foo(x) const; // This method will not modify the object

In case - through templates, for example - the implementation may vary, your interface must reflect the lowest common denominator. For const, for example, methods need to be non-const. For static, which is your question, you cannot declare static.

Note that this is not a huge imposition. Even if a method is static, you can still call it using with object semantics. So, in your case, you'll have to just use object semantics. In particular, regarding your clarification in the comments

If allocator is static then container doesn't need to hold it's pointer. So decorators must preserve staticness.

note that decorators can also not preserve staticness, because containers can hold pointers in any case, and call them via object notation, regardless of their constness.

Upvotes: 1

Related Questions