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) : ....
Related
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.
So I've used C for a long time and Java, too, but I'm not that familiar with C++. The situation is that we have:
base class template 1 -> base class template 2 -> several relevant subclasses
Currently all of the final subclasses inherit a member function from class 1, but we need to change the behavior of this function only in one of the subclasses, and only if a variable elsewhere in the code is set, and otherwise run the function as defined in class 1. Is there a way to do this without slotting the entire function definition on the other side of an if-else? I've looked at SFINAE/enable-if, but that's used for type-based decisions, not simple conditionals like this.
If I'm missing anything easy or dumb please let me know.
Some pseudocode might help:
template <class Face> class Publisher {
virtual void publish(...) {
// do stuff
}
}
template <class NewsType> class NewsPublisher : public Publisher<OnlineFace> {
// constructors, destructors...
}
class MagazinePublisher : public NewsPublisher<Sports> {
void publish(...) {
if(that.theOther() == value) {
// do different stuff
} else {
// do whatever would have been done without this override here
}
}
}
According to your example you can simply call the base class implementation explicitly:
class MagazinePublisher : public NewsPublisher<Sports> {
void publish(...) {
if(that.theOther() == value) {
// do different stuff
} else {
// call the base class implementation, as this function would not
// have been overridden:
NewsPublisher<Sports>::publish(...);
// ^^^^^^^^^^^^^^^^^^^^^^^
}
}
}
Well, I suppose your actual base class function publish() is declared as virtual member.
Also since your sample is just pseudo code and I couldn't really test it, you might need to add which publish() implementation should be used in the NewsPublisher<T> class:
template <class NewsType> class NewsPublisher : public Publisher<OnlineFace> {
public:
// constructors, destructors...
using Publisher<OnlineFace>::publish(); // <<<<<<<<<<<<<
}
Here's my issue, I'm trying to create a base class which can get a reference to a queue member in a derived class. I have two template functions in my base class :
class Base
{
template<TYPE type>
virtual void foo(std::queue<TYPE>*& typeQueue) //I know virtual isn't allowed
{
//do nothing as it's general case
}
template<typename TYPE>
void bar(TYPE type)
{
std::queue<TYPE>* typeQueue;
foo(typeQueue);
//... do some stuff with type
}
}
and a derived class which would theoretically be able to specialize the function foo for any types
class Derived : public Base
{
public:
template<>
void foo<int>(std::queue<int>*& m_integerQueue)
{
integerQueue= &m_integerQueue;
}
template<>
void foo<double>(std::queue<double>*& doubleQueue)
{
doubleQueue = &m_doubleQueue;
}
private:
std::queue<int> m_integerQueue;
std::queue<double> m_doubleQueue;
}
code above is more of about an ideology then a code to take word for word, I'd like the function bar to call the according function foo in derived class based on the type specified when bar is called. Of course this solution isn't working and the problem here is that we can't make template functions virtual.
I'm not sure if it's an error of design, but that's the general idea and I couldn't find an appropriate solution anywhere so I posted my own question here.
EDITED to make my problem clear
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)>
I'm finding it difficult to describe this problem very concisely, so I've attached the code for a demonstration program.
The general idea is that we want a set of Derived classes that are forced to implement some abstract Foo() function from a Base class. Each of the derived Foo() calls must accept a different parameter as input, but all of the parameters should also be derived from a BaseInput class.
We see two possible solutions so far, neither we're very happy with:
Remove the Foo() function from the base class and reimplement it with the correct input types in each Derived class. This, however, removes the enforcement that it be implemented in the same manner in each derived class.
Do some kind of dynamic cast inside the receiving function to verify that the type received is correct. However, this does not prevent the programmer from making an error and passing the incorrect input data type. We would like the type to be passed to the Foo() function to be compile-time correct.
Is there some sort of pattern that could enforce this kind of behaviour? Is this whole idea breaking some sort of fundamental idea underlying OOP? We'd really like to hear your input on possible solutions outside of what we've come up with.
Thanks so much!
#include <iostream>
// these inputs will be sent to our Foo function below
class BaseInput {};
class Derived1Input : public BaseInput { public: int d1Custom; };
class Derived2Input : public BaseInput { public: float d2Custom; };
class Base
{
public:
virtual void Foo(BaseInput& i) = 0;
};
class Derived1 : public Base
{
public:
// we don't know what type the input is -- do we have to try to cast to what we want
// and see if it works?
virtual void Foo(BaseInput& i) { std::cout << "I don't want to cast this..." << std::endl; }
// prefer something like this, but then it's not overriding the Base implementation
//virtual void Foo(Derived1Input& i) { std::cout << "Derived1 did something with Derived1Input..." << std::endl; }
};
class Derived2 : public Base
{
public:
// we don't know what type the input is -- do we have to try to cast to what we want
// and see if it works?
virtual void Foo(BaseInput& i) { std::cout << "I don't want to cast this..." << std::endl; }
// prefer something like this, but then it's not overriding the Base implementation
//virtual void Foo(Derived2Input& i) { std::cout << "Derived2 did something with Derived2Input..." << std::endl; }
};
int main()
{
Derived1 d1; Derived1Input d1i;
Derived2 d2; Derived2Input d2i;
// set up some dummy data
d1i.d1Custom = 1;
d2i.d2Custom = 1.f;
d1.Foo(d2i); // this compiles, but is a mistake! how can we avoid this?
// Derived1::Foo() should only accept Derived1Input, but then
// we can't declare Foo() in the Base class.
return 0;
}
Since your Derived class is-a Base class, it should never tighten the base contract preconditions: if it has to behave like a Base, it should accept BaseInput allright. This is known as the Liskov Substitution Principle.
Although you can do runtime checking of your argument, you can never achieve a fully type-safe way of doing this: your compiler may be able to match the DerivedInput when it sees a Derived object (static type), but it can not know what subtype is going to be behind a Base object...
The requirements
DerivedX should take a DerivedXInput
DerivedX::Foo should be interface-equal to DerivedY::Foo
contradict: either the Foo methods are implemented in terms of the BaseInput, and thus have identical interfaces in all derived classes, or the DerivedXInput types differ, and they cannot have the same interface.
That's, in my opinion, the problem.
This problem occured to me, too, when writing tightly coupled classes that are handled in a type-unaware framework:
class Fruit {};
class FruitTree {
virtual Fruit* pick() = 0;
};
class FruitEater {
virtual void eat( Fruit* ) = 0;
};
class Banana : public Fruit {};
class BananaTree {
virtual Banana* pick() { return new Banana; }
};
class BananaEater : public FruitEater {
void eat( Fruit* f ){
assert( dynamic_cast<Banana*>(f)!=0 );
delete f;
}
};
And a framework:
struct FruitPipeLine {
FruitTree* tree;
FruitEater* eater;
void cycle(){
eater->eat( tree->pick() );
}
};
Now this proves a design that's too easily broken: there's no part in the design that aligns the trees with the eaters:
FruitPipeLine pipe = { new BananaTree, new LemonEater }; // compiles fine
pipe.cycle(); // crash, probably.
You may improve the cohesion of the design, and remove the need for virtual dispatching, by making it a template:
template<class F> class Tree {
F* pick(); // no implementation
};
template<class F> class Eater {
void eat( F* f ){ delete f; } // default implementation is possible
};
template<class F> PipeLine {
Tree<F> tree;
Eater<F> eater;
void cycle(){ eater.eat( tree.pick() ); }
};
The implementations are really template specializations:
template<> class Tree<Banana> {
Banana* pick(){ return new Banana; }
};
...
PipeLine<Banana> pipe; // can't be wrong
pipe.cycle(); // no typechecking needed.
You might be able to use a variation of the curiously recurring template pattern.
class Base {
public:
// Stuff that don't depend on the input type.
};
template <typename Input>
class Middle : public Base {
public:
virtual void Foo(Input &i) = 0;
};
class Derived1 : public Middle<Derived1Input> {
public:
virtual void Foo(Derived1Input &i) { ... }
};
class Derived2 : public Middle<Derived2Input> {
public:
virtual void Foo(Derived2Input &i) { ... }
};
This is untested, just a shot from the hip!
If you don't mind the dynamic cast, how about this:
Class BaseInput;
class Base
{
public:
void foo(BaseInput & x) { foo_dispatch(x); };
private:
virtual void foo_dispatch(BaseInput &) = 0;
};
template <typename TInput = BaseInput> // default value to enforce nothing
class FooDistpatch : public Base
{
virtual void foo_dispatch(BaseInput & x)
{
foo_impl(dynamic_cast<TInput &>(x));
}
virtual void foo_impl(TInput &) = 0;
};
class Derived1 : public FooDispatch<Der1Input>
{
virtual void foo_impl(Der1Input & x) { /* your implementation here */ }
};
That way, you've built the dynamic type checking into the intermediate class, and your clients only ever derive from FooDispatch<DerivedInput>.
What you are talking about are covariant argument types, and that is quite an uncommon feature in a language, as it breaks your contract: You promised to accept a base_input object because you inherit from base, but you want the compiler to reject all but a small subset of base_inputs...
It is much more common for programming languages to offer the opposite: contra-variant argument types, as the derived type will not only accept everything that it is bound to accept by the contract, but also other types.
At any rate, C++ does not offer contravariance in argument types either, only covariance in the return type.
C++ has a lot of dark areas, so it's hard to say any specific thing is undoable, but going from the dark areas I do know, without a cast, this cannot be done. The virtual function specified in the base class requires the argument type to remain the same in all the children.
I am sure a cast can be used in a non-painful way though, perhaps by giving the base class an Enum 'type' member that is uniquely set by the constructor of each possible child that might possibly inherit it. Foo() can then check that 'type' and determine which type it is before doing anything, and throwing an assertion if it is surprised by something unexpected. It isn't compile time, but it's the closest a compromise I can think of, while still having the benefits of requiring a Foo() be defined.
It's certainly restricted, but you can use/simulate coviarance in constructors parameters.