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

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
};

Related

Specifying void* parameter in derived function

I would like to do something that probably is not possible in Cpp, but I could not find a post about this specifically.
I want to have a derived class specify the type of a void* parameter on a virtual function.
I have a base class called interface with a send function.
// pure virtual
class Interface{
virtual bool Send(const void*)=0;
};
struct Packet{
DataType data;
};
class SpecificInterface{
bool Send(const DataType*);
}
Is there a way to make something like this work? The intent is that SpecificInterface::Send implements Interface::Send. Allowing SpecificInterface to not be a pure virtual while restricting the void* to a specific packet type.
Otherwise I know I could take a void* parameter and static_cast it into the Packet* type; however, I do not want others to send a pointer type that cannot be cast to Packet*.
Let me know if this is not clear
When you want to override a virtual function, the number of arguments and the types of the arguments must exactly match the declaration in the base class. You'll have to use:
class SpecificInterface{
bool Send(const void* ptr)
{
cont DataType* dataTypePtr = static_cast<const DataType*>(ptr);
// Now use dataTypePtr any way you wish
}
};
Please note that use of such code is dangerous. If ptr does not really point to a DataType object, your program will have undefined behavior.
#RSahu is correct, of course. You could still use a virtual method to do about the same thing:
class Interface {
virtual bool send(const void*) = 0;
};
struct Packet {
DataType data;
};
class SpecificInterface {
bool send(cont void*) override {
send(static_cast<DataType*>(data));
}
bool send(cont DataType*); // code which actually does something
};
However - I recommend against your whole approach to begin with - it is massively unsafe, since the validity of the type is never checked! It's a source of many potential bugs. More often than not, you can avoid doing this. Here are a few things you might try instead:
std::any - a class which doesn't offer you compile-time type safety, but at least checks types at run-time. You would have a send(const std::any& data) virtual function, and inside it you would call std::any_cast<DataType>(data) to get a DataType or std::any_cast<DataType>(&data) to get a DataType *.
Probably even better - the Curiously-recurring template pattern (CRTP):
template <typename T>
class Interface {
virtual bool send(T*) = 0;
};
class SpecificInterface : Interface<DataType> {
bool send(cont DataType*) override;
}

C++ Template Method Overloading and Class Access with Polymorphism

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.

Give another class access to specific methods

I am working on game engine as a project during the summer. Every scriptable component should have access to some methods in the scene which they are in. To make this possible i pass lambdas from the scene that calls the respective methods to the scriptable where they are implicitly converted to std::function types.
Scene.h:
class Scene
{
private:
unsigned int _currentId;
std::vector<System*> _systems;
//SCRIPTABLE NEEDS THE BELOW METHODS THESE EXCLUSIVELY:
bool exists(unsigned id);
void destroy(unsigned int);
void addComponent(Component*, unsigned int);
template<typename T> T& getComponent(unsigned int);
template<typename T> bool hasComponent(unsigned int);
template<typename T> void removeComponent(unsigned int);
protected:
unsigned int instantiate(std::vector<Component*>);
public:
Scene(ChangeSceneCallback);
~Scene();
void initiate();
void update(long dt);
};
template<typename T>
inline T & Scene::getComponent(unsigned int id)
{
for (System* system : _systems) {
if (system->corresponds(T)) {
return static_cast<T*>(system->getComponent(entityId));
}
}
}
template<typename T>
inline bool Scene::hasComponent(unsigned int id)
{
for (System* system : _systems) {
if (system->corresponds(T)) {
return system->contains(id);
}
}
}
template<typename T>
inline void Scene::removeComponent(unsigned int id)
{
for (System* system : _systems) {
if (system->corresponds(T)) {
return system->destroy(id);
}
}
}
The callback method works for the non-template functions i need access to, but not the templated ones, so it's out of the question.
Scriptable:
typedef std::function<void(int)> ChangeSceneCallback;
typedef std::function<int(std::vector<Component*>)> InstantiateCallback;
typedef std::function<void(int)> DestroyCallback;
typedef std::function<bool(int)> ExistCallback;
typedef std::function<void(Component*, unsigned int)> AddComponentCallback;
class Scriptable: public Component
{
protected:
ChangeSceneCallback changeScene;
InstantiateCallback instantiate;
DestroyCallback destroy;
ExistCallback exists;
public:
~Scriptable();
Scriptable();
void assignCallbacks(ChangeSceneCallback, InstantiateCallback etc ...);
virtual void init() = 0;
virtual void update() = 0;
};
Scriptable can't have access to public methods in scene because this would give the user / developer access to them (Scriptable is a base class for the behaviour of the game). That is why i need to come up with something that gives scriptable limited access to scene.
Any thoughts?
You cannot have a type erased "template callback". You have to choose between the template or the type erasure. Let me explain.
This is what a "template callback" look like. This is in fact a generic lambda:
auto print_callback = [](auto var) {
std::cout << var << std::endl;
}
print_callback(4) ; // prints "4"
print_callback(4.5); // prints "4.5"
print_callback("hello"); // prints "hello"
It seems good but notice that you can't do that with std::function, since you have to predefine the signature.
std::function<void(int)> func_print_callback = print_callback;
func_print_callback(5); // Yay! Prints "5"
func_print_callback("hello"); // error
The thing is, you might think the limitation is only because std::function need a specific signature to work with, but the limitation is much deeper than that.
The thing is, the is no template function. They don't exists. Function template on the other hand, do exist. Why I emphasize so much on the order of my words is because the name of this thing says it all: it is not a function, it a template that is used to make functions.
Here's a simple example:
template<typename T>
void foo(T t) {
std::cout << t << std::endl;
}
This function is not compiled. Because it's not a function. No function foo will exist until the hole T has been filled.
How do you fill the hole named T supposed to be a type?
By filling it with a type of course!
foo(5.4); // the hole T is `double`
When the compiler sees this, it knows you need a function named foo that takes a double as parameter. There is no function named foo that takes a double. But we gave the compiler a tool to create one: the template!
So the compiler will generate this function:
void foo_double(double t) {
std::cout << t std::endl;
}
The word here is this: generate. The compiler need to create the function in order to exist. The compiler generate code for you.
When the function is generated and compiled, T do not exist anymore. A template parameter is a compile-time entity, and only the compiler knows about them.
Now, I'll explain to you why there is no such thing as a template callback.
Type erased container such as std::function are implemented with pointer to function. I'll use type aliases to ease the syntax a bit. It works like this:
// A function
void foo(int) {}
// The type of the pointer to function
using func_ptr = void(*)(int);
// A pointer to foo
func_ptr ptr = &foo;
The pointer to the function foo has a value that points to the location of foo in the memory.
Now imagine we have a way to have template function pointer. We would have to point to a function that does not exist yet. It has no memory location, so it cannot make sense. And through the pointer, when invoked as a function, you'd have to generate the function code.
Since a pointer to function can point to any function, even functions that aren't known to the compiler yet, you'd have to somehow generate the function code and compile it. But the value of the pointer, to which function our pointer points to, is defined at runtime! So you'd have to compile code at runtime, for code that you don't know yet, from a value that does not exist, when the compiler don't exist anymore. As you can see, pointer to template function, template std::function or virtual template function cannot exist.
Now that you have understood the problem, let me propose a solution: drop the callback usage. You should call those functions directly.
You seem to use callback only to be able to call private member functions. This is the wrong way to do it, even if it works. What you need is friend, the feature of C++ that allows you to access private members.
class Scene {
friend Component;
// ...
};
class Component {
protected:
// Let `scene` be a reference to your scene
void addComponent(Component* c, unsigned int id) {
scene.addComponent(c, id);
}
template<typename T>
T& getComponent(unsigned int id) {
return scene.getComponent<T>(id);
}
template<typename T>
bool hasComponent(unsigned int id) {
return scene.hasComponent(id);
}
template<typename T>
void removeComponent(unsigned int id) {
removeComponent(id);
}
// ...
};
Since the Component class is the only friend to Scene, only it can call private member functions. Since all those newly defined functions in Component are protected, only class that extends from Component can call those. They are invoked like this:
class Scriptable : public Component {
void foo() {
hasComponent<Bar>(87); // works, call function defined in `Component`
}
};

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)>

c++ - accessing derived class method via abstract template base class interface pointer, without explicit type in interface

This is my first post. I have spent hours checking for a solution on my problem, searching link after link on SO, but none descried my problem exactly(the closest i could get were this and this). So, let's get to work!
Description: I must implement a collection of specialized classes, each one able to store a linked list of its type. Also (the tricky part), I must implement a collection manager, in a way that adding more specialized classes to the collection does not affect its code.
Let me explain what I have so far.
class IList {
public:
virtual IList& operator+( IList&) = 0;
virtual void print() = 0;
virtual int g_Size() const = 0;
//perfect till here
virtual void Push(const int&) = 0;//needs to be upgraded
virtual const int& operator[](int index) = 0;//needs to be upgraded
};
template<class T>
class Queue: public IList{
//internal stuff
public:
Queue();
int g_Size() const;
void print();
void Push(const T& cv);
const T& operator[](int index);
~Queue();
};//all implementation of Queue<T> is implemented and working, but removed for simplicity
class CIntList : public Queue<int>{
//stuff here, specialized on int
};
class C_Manager{
IList * classes[3];//notice the polymorphism, managing the class collection using a pointer to the common(base) interface
public:
void testing()
{
for (int i = 0; i < 3; i++)
classes[i] = new CIntList(i);
classes[0]->Push(1); classes[0]->Push(2); classes[1]->Push(1121); classes[2]->Push(12);
classes[0]->print();
classes[2]->print();
int a = classes[0]->operator[](1);
classes[1]->Push(a + a);
} //working fine
};
OK, so you`ll maybe ask, what is the question?
I do not want to redeclare the Push and operator[] (or any other function that uses the template as argument) for all of my classes specializations. More exactly, if I want to add, let's say,
class CFloatList: public Queue<float>
{
//float stuff goes here
};
I must also modify IList to
class IList {
public:
virtual IList& operator+( IList&) = 0;
virtual void print() = 0;
virtual int g_Size() const = 0;
//perfect till here
virtual void Push(const int&) = 0;//used for int
virtual const int& operator[](int index) = 0;//used for int
//NEW DECLARATION FOR FLOAT
virtual void Push(const float&) = 0;//used for float
virtual const float& operator[](int index) = 0;//used for float
};
How can I avoid these redeclarations? I need sort of "virtual function templates", but this is not supported in C++.
Is my approach wrong?
Sorry for not highlighting the c++ syntax, this is my first post and I only managed to format it in code blocks. Thank you for your time!
EDIT #1
A BETTER SOLUTION(as suggested by jaggedSpire - many, many thanks)
I have modified IList to
class IList {
public:
virtual IList& operator+( IList&) = 0;
virtual void afis() = 0;
virtual int g_Size() const = 0;
//templates
template<typename T>
void Push(const T& arg) //WORKS PERFECTLY
{
Queue<T>* cast = dynamic_cast<Queue<T>*>(this);
cast->Push(arg);
}
template<typename T>
const T& operator[](int index) //error
{
Queue<T>* cast = dynamic_cast<Queue<T>*>(this);
return cast->operator[](index);
}
};
and void C_Manager::testing() to
class C_Manager{
public:
void testing()
{
IList * a = new CIntList(1);
a->Push(200);//WORKS PERFECTLY
int c = a->operator[](0); //ERROR
}
};
and it produces these errors
Error C2783 'const T &IList::operator [](int)': could not deduce template argument for 'T'
Error C2672 'IList::operator []': no matching overloaded function found
intellisense: no instance of function template "IList::operator[]" matches the argument list
Basically, it complains about every possibly templated function that has a T-related return type. How can I fix this to make my manager truly polymorphic?
First, let's review your requirements:
Have a non-templated polymorphic base class, IList
Have a class template, Queue<T> inherit from the base class to implement it.
Be able to specialize the Queue<T> however you want
Presumably, given you're returning void from push, and const T& from operator[], you want to signal errors with an exception.
Pass in a parameter of a specific type to the base class IList, and have the resulting behavior depend on whether the underlying type of Queue<T> matches the type of the given parameter.
This last bit is the key: you're trying to choose behavior of a function based off of both the runtime type of the caller and the static type of the argument. However, which type actually matches the T in the implementing Queue<T> is determined at runtime.
Runtime determination of behavior based off of the runtime types of two objects (because the argument is known at runtime as well as compile time) is what multi-methods are for. C++ doesn't have native multi-method support, but it can be pieced together with dynamic_cast
I picked up on the similarity to your present issue through this answer, which provides a wonderful array of links for more details on implementing (and implementations of) full multi-method functionality in C++.
Now, a brute-force/naive implementation of multi-methods in C++ would require testing the arguments for every possible implementing type from a list of implementing types. This is something you've also indicated you don't want, but not to worry: you won't need to. This is because we only want to test one circumstance, rather than the many required of a typical multi-method situation. We're handed the type of the argument to add at compile time, when we can conveniently use that information to find the type of the only destination type we're interested in.
For a supplied type of T, we want to test whether the type we're dispatching to is really Queue<T>.
To do that, we're going to use the same test used in the simpler multi-method implementations: dynamic_cast. Specifically, we're going to cast the this pointer to the type we're testing for, using the provided argument type as the source for the template argument required.
Be warned: this means that implicit conversion between types won't happen without an explicit template argument. If you pass in a string literal to your std::string container and don't explicitly specify that you want a std::string container, it's going to look for a container that holds character arrays the length of your string literal, and detect none. They're different types, after all.
With that said, let's get to the code. For an interface Parent that is implemented by a variety of Child<T>, you can use this to get T specific behavior from a Child<T> accessible only through a Parent interface:
class Parent{
public:
template <typename T>
void foo(const T& t);
virtual ~Parent(){}
};
template <typename T>
class Child : public Parent{
public:
void foo(const T& t);
};
// must be after the definition of the Child template,
// because dynamic_cast requires a complete type to target
template <typename T>
void Parent::foo(const T& t){
// throws on bad conversion like we want
auto castThis = dynamic_cast<Child<T>&>(*this);
// if execution reaches this point, this is a Child<T>
castThis.foo(t);
}
With:
template<typename T>
void Child<T>::foo(const T& t){
std::cout << typeid(T).name() << ": " << t << '\n';
}
int main(){
Parent&& handle = Child<int>();
try{
handle.foo<int>(3);
handle.foo<char>(0);
handle.foo<std::string>("Hello!");
}
catch(std::bad_cast e){
std::cout << "bad cast caught\n";
}
}
We get the following output on both g++ 5.2.0 and clang 3.7
i: 3
bad cast caught
Which is what we wanted.
Once you have the simple polymorphic interface presented here, implementing your collection should be easy. I'd go with a wrapper class around a std::vector<std::unique_ptr<Parent>> myself, but that decision is ultimately up to you.
Now, because this wasn't enough of a wall of text, some notes:
Throwing an exception is not good for standard control flow. If you don't actually know whether or not an argument matches the underlying type via some external logic, you want some other form of error handling. dynamic_cast may be used to cast both references and pointers. Casting a reference to an object not of the target type will throw std::bad_cast. Casting a pointer will return a null pointer.
Using the same name for a member function in a derived class as a templated member function calling that member function in the base class works because of the way name lookup works in C++. From this answer:
The basic algorithm is the compiler will start at the type of the current value and proceed up the hierarchy until it finds a member on the type which has the target name. It will then do overload resolution on only the members of that type with the given name. It does not consider members of the same name on parent types.
So the lookup for foo will start in Child<T>, and since it finds a member function with that name inside Child<T>, it doesn't examine Parent or call the dispatching function again.
3. I would consider why I'm doing this carefully before actually using this sort of workaround.