C++ Template Method Overloading and Class Access with Polymorphism - c++

I noticed something which I think is pretty interesting behaviour.
Consider the following example code which I tried to keep as generic as possible:
class Base
{
public:
virtual void func() {}
};
class Subclass : public Base
{
public:
void func() {}
};
class ApplyingClass
{
public:
static void callFunc(Base& base) { base.func(); }
private:
template <class T>
static void callFunc(T& t) { t.func(); }
};
int main()
{
Subclass s;
Base& b = s;
// Error: ApplyingClass::callFunc(T& t) with T=Subclass is private.
ApplyingClass::callFunc(s);
// works
ApplyingClass::callFunc(b);
return 0;
}
It seems that inside main(), due to the template method being present, the compiler sees the template "ApplyingClass::callFunc(T& t)" as the right fit for the function call "ApplyingClass::callFunc(s)" and throws an Error since the method is not accessible from outside it's class.
This seems logical, yet I expected the compiler to still go and try to use "ApplyingClass::callFunc(Base& base)" since the method signature fits and this is the only accessible fitting method.
To take my point a bit further; if I were to remove the private template method from ApplyingClass, both function calls inside main() would be valid.
My question now is whether this is part of the C++ specification or if this is compiler specific behaviour (this was tested using the Visual Studio 2017 ver 15.5.7 compiler).

It's valid C++ to emit an error here.
See [class.member.lookup]:
If the name of an overloaded function is unambiguously found, overload resolution also takes place before
access control.
So the appropriate overload is selected first (the template), and then access control happens, which causes a compiler error.

Related

How to self-document a callback function that is called by template library class?

I have a function User::func()(callback) that would be called by a template class (Library<T>).
In the first iteration of development, everyone know that func() serves only for that single purpose.
A few months later, most members forget what func() is for.
After some heavy refactoring, the func() is sometimes deleted by some coders.
At first, I didn't think this is a problem at all.
However, after I re-encountered this pattern several times, I think I need some counter-measure.
Question
How to document it elegantly? (cute && concise && no additional CPU cost)
Example
Here is a simplified code:-
(The real world problem is scattering around 10+ library-files & 20+ user files & 40+ functions.)
Library.h
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
node->func(); //#1
}
};
User.h
class User{
public: void func(){/** some code*/} //#1
//... a lot of other functions ...
// some of them are also callback of other libraries
};
main.cpp
int main(){
Library<User> li; .... ; li.utility();
}
My poor solutions
1. Comment / doc
As the first workaround, I tend to add a comment like this:-
class User{
/** This function is for "Library" callback */
public: void func(){/** some code*/}
};
But it gets dirty pretty fast - I have to add it to every "func" in every class.
2. Rename the "func()"
In real case, I tend to prefix function name like this:-
class User{
public: void LIBRARY_func(){/** some code*/}
};
It is very noticeable, but the function name is now very longer.
(especially when Library-class has longer class name)
3. Virtual class with "func()=0"
I am considering to create an abstract class as interface for the callback.
class LibraryCallback{
public: virtual void func()=0;
};
class User : public LibraryCallback{
public: virtual void func(){/** some code*/}
};
It provides feeling that func() is for something-quite-external. :)
However, I have to sacrifice virtual-calling cost (v-table).
In performance-critical cases, I can't afford it.
4. Static function
(idea from Daniel Jour in comment, thank!)
Almost 1 month later, here is how I use :-
Library.h
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
T::func(node); //#1
}
};
User.h
class User{
public: static void func(Callback*){/** some code*/}
};
main.cpp
int main(){
Library<User> li;
}
It is probably cleaner, but still lack self-document.
func is not a feature of User. It is a feature of the User-Library<T> coupling.
Placing it in User if it doesn't have clear semantics outside of Library<T> use is a bad idea. If it does have clear semantics, it should say what it does, and deleting it should be an obviously bad idea.
Placing it in Library<T> cannot work, because its behavior is a function of the T in Library<T>.
The answer is to place it in neither spot.
template<class T> struct tag_t{ using type=T; constexpr tag_t(){} };
template<class T> constexpr tag_t<T> tag{};
Now in Library.h:
struct ForLibrary;
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
func( tag<ForLibrary>, node ); // #1
}
};
in User.h:
struct ForLibrary;
class User{
/** This function is for "Library" callback */
public:
friend void func( tag_t<ForLibrary>, User* self ) {
// code
}
};
or just put this into the same namespace as User, or the same namespace as ForLibrary:
friend func( tag_t<ForLibrary>, User* self );
Before deleting func, you'll track down ForLibrary.
It is no longer part of the "public interface" of User, so doesn't clutter it up. It is either a friend (a helper), or a free function in the same namespace of either User or Library.
You can implement it where you need a Library<User> instead of in User.h or Library.h, especially if it just uses public interfaces of User.
The techniques used here are "tag dispatching", "argument dependent lookup", "friend functions" and preferring free functions over methods.
From the user side, I would use crtp to create a callback interface, and force Users to use it. For example:
template <typename T>
struct ICallbacks
{
void foo()
{
static_cast<T*>(this)->foo();
}
};
Users should inherit from this interface and implement foo() callback
struct User : public ICallbacks<User>
{
void foo() {std::cout << "User call back" << std::endl;}
};
The nice thing about it is that if Library is using ICallback interface and User forget to implement foo() you will get a nice compiler error message.
Note that there is no virtual function, so no performance penalty here.
From the library side, I would only call those callbacks via its interfaces (in this case ICallback). Following OP in using pointers, I would do something like this:
template <typename T>
struct Library
{
ICallbacks<T> *node = 0;
void utility()
{
assert(node != nullptr);
node->foo();
}
};
Note that things get auto documented in this way. It is very explicit that you are using a callback interface, and node is the object who has those functions.
Bellow a complete working example:
#include <iostream>
#include <cassert>
template <typename T>
struct ICallbacks
{
void foo()
{
static_cast<T*>(this)->foo();
}
};
struct User : public ICallbacks<User>
{
void foo() {std::cout << "User call back" << std::endl;}
};
template <typename T>
struct Library
{
ICallbacks<T> *node = 0;
void utility()
{
assert(node != nullptr);
node->foo();
}
};
int main()
{
User user;
Library<User> l;
l.node = &user;
l.utility();
}
Test.h
#ifndef TEST_H
#define TEST_H
// User Class Prototype Declarations
class User;
// Templated Wrapper Class To Contain Callback Functions
// User Will Inherit From This Using Their Own Class As This
// Class's Template Parameter
template <class T>
class Wrapper {
public:
// Function Template For Callback Methods.
template<class U>
auto Callback(...) {};
};
// Templated Library Class Defaulted To User With The Utility Function
// That Provides The Invoking Of The Call Back Method
template<class T = User>
class Library {
public:
T* node = nullptr;
void utility() {
T::Callback(node);
}
};
// User Class Inherited From Wrapper Class Using Itself As Wrapper's Template Parameter.
// Call Back Method In User Is A Static Method And Takes A class Wrapper* Declaration As
// Its Parameter
class User : public Wrapper<User> {
public:
static void Callback( class Wrapper* ) { std::cout << "Callback was called.\n"; }
};
#endif // TEST_H
main.cpp
#include "Test.h"
int main() {
Library<User> l;
l.utility();
return 0;
}
Output
Callback was called.
I was able to compile, build and run this without error in VS2017 CE on Windows 7 - 64bit Intel Core 2 Quad Extreme.
Any Thoughts?
I would recommend to name the wrapper class appropriately, then for each specific call back function that has a unique purpose name them accordingly within the wrapper class.
Edit
After playing around with this "template magic" well there is no such thing...
I had commented out the function template in the Wrapper class and found that it is not needed. Then I commented out the class Wrapper* that is the argument list for the Callback() in User. This gave me a compiler error that stated that User::Callback() does not take 0 arguments. So I looked back at Wrapper since User inherits from it. Well at this point Wrapper is an empty class template.
This lead me to look at Library. Library has a pointer to User as a public member and a utility() function that invokes User's static Callback method. It is here that the invoking method is taking a pointer to a User object as its parameter. So it lead me to try this:
class User; // Prototype
class A{}; // Empty Class
template<class T = User>
class Library {
public:
T* node = nullptr;
void utility() {
T::Callback(node);
}
};
class User : public A {
public:
static void Callback( A* ) { std::cout << "Callback was called.\n"; }
};
And this compiles and builds correctly as the simplified version. However; when I thought about it; the template version is better because it is deduced at compile time and not run time. So when we go back to using templates javaLover had asked me what class Wrapper* means or is within the argument list for the Callback method within the User class.
I'll try to explain this as clearly as I can but first the wrapper Class is just an empty template shell that User will inherit from and it does nothing but act as a base class and it now looks like this:
template<class T>
class Wrapper { // Could Be Changed To A More Suitable Name Such As Shell or BaseShell
};
When we look at the User class:
class User : public Wrapper<User> {
public:
static void Callback( class Wrapper* ) { // print statement }
};
We see that User is a non-template class that inherits from a template class but uses itself as the template's argument. It contains a public static method
and this method doesn't return any thing but it does take a single parameter; this is also evident in the Library class that has its template parameter as a User class. When the Library's utility() method invokes User's Callback() method the parameter that the Library is expecting is a pointer to a User object. So when we go back to the User class instead of declaring it as a User* pointer directly in its declaration I'm using the empty class template that it inherits from. However if you try to do this:
class User : public Wrapper<User> {
public:
static void Callback( Wrapper* ) { // print statement }
};
You should get a message that Wrapper* is missing it's argument list. We could just do Wrapper<User>* here but that is redundant since we already see that User is inheriting from Wrapper that takes itself. So we can fix this and make it cleaner just by prefixing the Wrapper* with the class keyword since it is a class template. Hence the template magic... well there is no magic here... just compiler intrinsic and optimizations.
While I know that I don't answer your specific question (how to document the not-to-be-deleted function) I would solve your problem (keeping the seemingly unused callback function in the code base) by instantiating Library<User> and calling the utility() function in a unit test (or maybe it should rather be called an API test...). This solution would probably scale to your real world example too, as long as you don't have to check each possible combination of library classes and callback functions.
If you are lucky enough to work in an organization where successful unit tests and code review are required before changes go into the code base this would require a change to the unit tests before anyone could remove the User::func() function and such a change would probably catch the attention of a reviewer.
Then again, you know your environment and I don't, and I'm aware that this solution doesn't fit all situations.
Here is a solution using a Traits class:
// Library.h:
template<class T> struct LibraryTraits; // must be implemented for every User-class
template<class T> class Library {
public:
T* node=nullptr;
void utility() {
LibraryTraits<T>::func(node);
}
};
// User.h:
class User { };
// must only be implemented if User is to be used by Library (and can be implemented somewhere else)
template<> struct LibraryTraits<User> {
static void func(User* node) { std::cout << "LibraryTraits<User>::func(" << node << ")\n"; }
};
// main.cpp:
int main() {
Library<User> li; li.utility();
}
Advantages:
It is obvious by the naming that LibraryTraits<User> is only required for interfacing User by Library (and can be removed, once either Library or User gets removed.
LibraryTraits can be specialized independent of Library and User
Disadvantages:
No easy access to private members of User (making LibraryTraits a friend of User would remove the independence).
If the same func is needed for different Library classes multiple Trait classes need to be implemented (could be solved by default implementations inheriting from other Trait classes).
This heavily reminds an old good Policy-Based Design, except in your case you do not inherit the Library class from the User class.
Good names are the best friends of any API. Combine this and the well-known patter of Policy-Based Design (well-known is very important because the class names with the word Policy in it will immediately ring the bell in many readers of the code) and, I assume, you get a well self-documenting code.
Inheritance won't give you any performance overhead, but will give you an ability to have the Callback as a protected method, that will give some hint that it is supposed to be inherited and be used somewhere.
Have clearly standing-out and consistent naming among multiple User-like classes (e.g. SomePolicyOfSomething in the manner of aforementioned Policy-Based Design), as well as, the template arguments for the Library (e.g SomePolicy, or I would call it TSomePolicy).
Having using declaration of the Callback in the Library class might give much clearer and earlier errors (e.g. from IDE, or modern clang, visial studio syntax parsers for IDE).
Another arguable option might be a static_assert if you have C++>=11. But in this case it must be used in every User-like class ((.
Not a direct answer to your question on how to document it, but something to consider:
If your Library template requires an implementation of someFunction() for each class to be used in it, i'd recommend adding it as a template argument.
#include <functional>
template<class Type, std::function<void(Type*)> callback>
class Library {
// Some Stuff...
Type* node = nullptr;
public:
void utility() {
callback(this->node);
}
};
Might make it even more explicit, so that other devs know it's needed.
abstract class is the best way to enforce the function not to be deleted. So i recommend implementing the base class with pure virtual function, so that derived has to define the function.
OR second solution would be to have function pointers so that performance will be saved by avoiding extra overhead of V-table creation and calling.
If it is not obvious that func() is needed in User, then I'd argue you're violating the single responsibility principle. Instead create an adapter class of which User as a member.
class UserCallback {
public:
void func();
private:
User m_user;
}
That way the existance of UserCallback documents that func() is an external call back, and separates out Library's need of a callback from the actual responsibilities of User.

Is there a way to detect if a function is overridden?

Suppose we have an abstract Base class that is inherited:
class Base
{
protected:
Base() {}
virtual ~Base() {}
virtual void on_event_foo(int) {}
virtual void on_event_bar(int) {}
};
struct Concrete : public Base
{
virtual void on_event_foo(int value) {/*do some stuff with #value*/}
};
Is it a way to know (at compile time would be the best) the virtual functions from Base that was overridden (with some code in constructor, or with a special pattern)?
My purpose is to implement a wrapper for a library that use some callbacks ; and if I can do check the overriden functions, I will create only the callbacks the user wants.
I want the user can choose the function he wants to override. Then in my code, I will create callbacks only for the overridden functions. The pure virtual functions are not a solution, because they cannot permit to create a concrete class without overriding all of them.
In the constructor of Base, for now, I connect a lot of static callback functions of Base within a C API. In those functions, I call the corresponding member function. For example, the callback function is static Base::EventFoo(/* ... */) that calls inside object->on_event_foo(/* .. */). This is because I cannot give a member function as a callback to a C library.
But creating too much callbacks make my wrapper slower. So, I want to connect only the callback that the user wants, ie knowing the functions there are overriden by him.
Disclaimer: I've been notified that this behavior is unspecified since it relies on comparing virtual member function pointers:
[expr.eq] ... if either is a pointer to a virtual member function, the result is unspecified.
Wording is present in all C++ standards (that I could check). Your results may vary.
If you are willing to change a few things, you can use the curiously recurring template pattern to determine if the function is overridden
#include <iostream>
template <class Derived>
struct Base
{
virtual void on_event() {}
void raise_event()
{
if (&Derived::on_event == &Base::on_event)
std::cout << "not overridden" << std::endl;
else
std::cout << "overridden" << std::endl;
}
};
struct Concrete1 : Base<Concrete1>
{
virtual void on_event() override {}
};
struct Concrete2 : Base<Concrete2>
{
// no override
};
int main()
{
Concrete1 c1;
Concrete2 c2;
c1.raise_event(); // prints overridden
c2.raise_event(); // prints not overridden
return 0;
}
The statement &Derived::on_event == &Base::on_event should be resolved at compile-time (if that's what you're worried about) and the if can be optimized away.
Though I agree with others' opinions that this seems like a poor pattern. It would be much simpler to have the base class have empty event handlers like you already have.
Don't use virtual methods at all. If all you want is given some concrete type, Concrete, to hook it up to a bunch of callbacks based on the presence of member functions then we can use templates.
For a given type and function name, we can determine if &T::func exists at compile time. If it does, we add that callback. So we end up with a whole bunch of things like:
template <class T>
void setup_cbs(T& object) {
T* ptr_to_object = ...; // store somewhere
static_if<has_on_event_foo<T>>(
[](auto ptr){
add_event_foo_callback(ptr, [](void* p, int i) {
using U = decltype(ptr);
static_cast<U>(p)->on_event_foo(i);
})
}),
[](auto ){}
)(ptr_to_object);
I'm assuming the callback adder takes a pointer and a callback. You will separately have to figure out how to store the pointers, but that seems easier.
With modern c++ you can do this:
if constexpr (!std::is_same_v<decltype(&Derived::foo), decltype(&Base::foo)>) {
std::cout << "overrided" << std::endl;
}
You may want to define a macro like this:
#define OVERRIDED(B, D, name) !std::is_same_v<decltype(&B::name), decltype(&D::name)>

Taking a pointer to a protected method of the base class and passing it to a different class

template <typename... Arguments>
class CCallback
{
public:
template <class TargetClass>
CCallback(TargetClass * target, void (TargetClass::*targetMethod)(Arguments...))
{
}
};
struct TargetClassBase
{
protected:
void f() {}
};
struct TargetClassChild : TargetClassBase
{
void g() {}
void test()
{
CCallback<> callback(this, &TargetClassChild::f);
}
} child;
void main()
{
}
That code doesn't compile in MSVC 2013:
error C2660: 'CCallback<>::CCallback' : function does not take 2
arguments
I don't understand why I get this specific error, and how to make it work. There are no further details about the error logged by the compiler.
And, of course, I can't properly specify that the method belongs to the base class (&TargetClassBase::f)- taking a pointer to a non-public base method is forbidden.
Problem with your code is that compiler cannot deduce template type TargetClass in constructor for CCallback. This is because you pass arguments of types: TargetClassChild* and void (TargetClassBase::*)() to constructor. This is not a typo. Even if you write &TargetClassChild::f this expression still has type: pointer to function returning void in class TargetClassBase and not TargetClassChild as one could expect.
This kind of issues can be solved in two ways:
You could specify template type explicitly, but in this particular case it cannot be done because in C++ there is no way to explicitly pass template parameters to constructors as constructors don't have names (according to note in ยง14.5.2.5 of c++ standard).
Pass arguments of appropriate types to function. In this case simply cast your function to appropriate type like this static_cast<void (TargetClassChild::*)()>(&TargetClassChild::f)
Expanding on robal's perfectly correct answer, I've rewritten the constructor of my class so that I don't need a manual type cast:
template <class TargetInstanceClass, class TargetMethodClass>
CCallback(TargetInstanceClass * target, void (TargetMethodClass::*targetMethod)(Arguments...))
{
void (TargetInstanceClass::*targetInstanceMethod)(Arguments...) = static_cast<void (TargetInstanceClass::*targetInstanceMethod)(Arguments...)>(targetMethod);
}

templated class : accessing derived normal-class methods

I have something like this :
class Container1 {
public:
method1() { ... }
}
class Container2 {
public:
method1() { ... }
}
template<class C = Container1>
class X : public C {
public:
using C::method1();
.....
X(string& str) : C(str) {};
X& other_method() { method1(); ...; }
}
My question is why I have to use "using C::method1()", to be able to access the method..
Most of answers I found is for the case where templated-class inhering templated-class. Normally they mention using "this->", but this does not seem to work in this case.
Can I do something else shorter...
Also I'm suspecting the other error I'm getting is related to the same problem :
no match call for (X<Container1>) (<std::string&>)
First of all, in the definition of the ctor you should not use <C>. Most likely this confuses the compiler:
template<class C = Container1>
class X : public C
{
X(string& str) : C(str) { }
X& other_method() { method1(); ...; }
}
Other point is that compiler may be not sure what should it call: base_class::method1() or template_param::method1(). In reality this is the same thing, but compiler may have a problem understanding this. I would not be surprised if different compilers will act differently here.
These are my 2 cents without running the tests.
Calling this->method1() probably fails since Container1::method1 and Container2::method1 are private. You can fix this by doing:
class Container1 {
public:
void method1() { ... }
};
Then, going back to "why do I have to use using or this-> when calling methods defined in a template base class?", the answer is that method1 here is a dependent name, since it depends on the template argument C. Therefore you need to tell the compiler "Hey, you see this method1 call? Well, that symbol should be defined in the template class I'm inheriting.".
Since the compiler doesn't know what you're inheriting until you actually instantiate the class template, you must indicate that the member function should be defined by that template parameter. Otherwise, the compiler will see a call to a non-qualified function, and will generate an error, since no method named "method1" can be found in class X.
This thread contains some information on what dependent names are.
Another error in your code is your constructor:
X<C>(string& str) : ...
That code is ill-formed. The class X's constructor constructor should be defined this way:
X(string& str) : ....

Why does C++ prefer this template method to a method overload?

Assuming I had two classes, the first one for writing primitive types (bool, int, float, etc.) and the second one extending the first to also write complex types:
struct Writer {
virtual void Write(int value) = 0;
};
struct ComplexWriter : public Writer {
template <typename TValue> void Write(const TValue &value) {
boost::any any(value);
Write(any);
}
//virtual void Write(int value) = 0; // see question below
virtual void Write(const boost::any &any) = 0;
};
The idea is that if someone calls myWriter.Write(someIntValue);, the int overload will receive priority over the templated method.
Instead, my compiler (Visual C++ 11.0 RC) always picks the template method. The following code snippet, for example, will print Wrote any to the console:
struct ComplexWriterImpl : public ComplexWriter {
virtual void Write(int value) { std::cout << "Wrote an int"; }
virtual void Write(const boost::any &any) { std::cout << "Wrote any"; }
};
void TestWriter(ComplexWriter &writer) {
int x = 0;
writer.Write(x);
}
int main() {
ComplexWriterImpl writer;
TestWriter(writer);
}
The behavior suddenly changes when I declare the Write(int) method in the ComplexWriter class as well (see commented out line in the first snippet). It then prints Wrote an int to the console.
Is this how my compiler ought to behave? Does the C++ standard explicitly say that only overloads defined in the same class (and not a base class) shall be prioritized over a templated method?
The problem is that at the point you're calling writer.Write(x) the compiler sees a ComplexWriter not a ComplexWriterImpl, so it is only aware of the functions defined in ComplexWriter - the template function and the boost::any function.
ComplexWriter does not contain any virtual functions that accept an int, so it has no way to call through to the int overload defined in ComplexWriterImpl
When you add in the virtual overload to the ComplexWriter class, then the compiler becomes aware that there is an integer overload in the ComplexWriter class and therefore calls through to it's implementation in ComplexWriterImpl
EDIT: Now that you've edited in the inheritance between ComplexWriter & Writer, I've got a more complete explanation for you:
When you create a subclass and define a function in it then all of the functions of that name in the base class will be hidden, regardless of their argument types.
You can get around this with the using keyword I believe:
struct ComplexWriter : public Writer {
template <typename TValue> void Write(const TValue &value) {
boost::any any(value);
Write(any);
}
using Writer::Write;
virtual void Write(const boost::any &any) = 0;
};
For more details see this FAQ entry: http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9
EDIT 2: Just to confirm that this does indeed solve your problem: http://ideone.com/LRb5a
When you access the object via the ComplexWriter "interface", the compiler will try to resolve the function call to Write(int) using the definitions in that class. If it does not able to do so, it will consider base classes.
In this case, you have two candidates: Write(any) and the templated version. Since there is no explicit Write(int) available at this point, it will have to choose between these two options. Write(any) requires an implicit conversion, while the templated version does not, so the templated version is called (which in turn calls Write(any)).
To make the Write(int) from Writer available, import the Writer::Write functions:
class ComplexWriter : public Writer
{
using Writer::Write;
// rest is as before
};