template member function inheritance - c++

I have a non-template class with a template member function similar to below.
class Component
{
public:
static const int HASH_ID = 0;
virtual int HashID() const {return Component::HASH_ID;}
virtual bool is(int hash_id) const {return Component::HASH_ID == hash_id;}
template<typename T> bool is() const {return this->is(T::HASH_ID);}
};
class Transform : public Component
{
public:
static const int HASH_ID = 1;
virtual int HashID() const {return Transform::HASH_ID;}
virtual bool is(int hash_id) const {return Transform::HASH_ID == hash_id;}
};
My issue is that the Transform class won't let me call the template function.
Here is the test code I wrote that won't compile
int main(void)
{
Transform test_component;
Transform* transform = &test_component;
Component* component = &test_component;
std::cout << component->is<Transform>() << std::endl; //No issues
//Won't compile unless I comment out this line
std::cout << transform->is<Transform>() << std::endl; //Says I am missing argument list
std::cout << transform->is(Transform::HASH_ID) << std::endl; //Works Fine!
return 0;
}
Any ideas why this doesn't work?

virtual bool is(int hash_id) const {return Transform::HASH_ID == hash_id;}
is hiding
template<typename T> bool is() const {return this->is(T::HASH_ID);}
If a derived class declares a method with the same name as a method defined by the base class, the derived class' method hides the base class' one.

Related

Specialized inheritance of a templated class causes member function to return templated class type rather than inherited class type

Assume I have a base class like this:
template<typename T>
class Base {
public:
Base& operator()(const T& value) {
this->value = value;
return *this;
}
T value;
};
Now I want to inherit from this class to create type-specific classes
class InheritedFloat : public Base<float> {} inheritedFloat;
Now here I try to catch this inheritance in a functon:
void function(const InheritedFloat& inherited) {
std::cout << inherited.value << '\n';
}
Calling this function like this works fine, of course:
int main() {
function(inheritedFloat); //(inheritedFloat is a global instance)
return 0;
}
But when I try to call it with the operator()(const float& value){...} member function, function(const InheritedFloat& inherited){...} doesn't see it as a InheritedFloat-Type but instead as a Base<float>-Type:
int main() {
function(inheritedFloat(10.f)); //error
return 0;
}
Error:
Error C2664 'void function(const InheritedFloat &)': cannot convert argument 1 from 'Base<float>' to 'const InheritedFloat &'
So how can I make operator()(const T& value){...} return InheritedFloat& instead of Base<float>&?
To clearify further, this is just a simplified example (of course). I have dozens of inheritance cases. So I can't just template-specify function()
template<typename T>
void function(const Base<T>& inherited) {
std::cout << inherited.value << '\n';
}
because each inheritance needs to be treated differently. Types will overlap, so there will be multiple Base<std::size_t> cases, for example.
The whole code:
#include <iostream>
template<typename T>
class Base {
public:
Base& operator()(const T& value) {
this->value = value;
return *this;
}
T value;
};
class InheritedFloat : public Base<float> {} inheritedFloat;
void function(const InheritedFloat& inherited) {
std::cout << inherited.value << '\n';
}
int main() {
function(inheritedFloat(10.f));
return 0;
}
Thanks for reading, I appreciate any help!
You can utilize CRTP here. By supplying extra template parameter you can make base class function return a reference to a derived class:
#include <iostream>
template<typename Derived, typename T>
class Base {
public:
Derived & operator()(const T& value) {
this->value = value;
return *static_cast<Derived *>(this);
}
T value;
};
class InheritedFloat : public Base<InheritedFloat, float> {} inheritedFloat;
void function(const InheritedFloat& inherited) {
std::cout << inherited.value << '\n';
}
int main() {
function(inheritedFloat(10.f));
return 0;
}
online compiler

Use both type and integer as template parameter

For the code I am working on, I have a class that uses a "context" singleton. In order to be a bit more coder-friendly, I passes the Singleton class used as a template to the object. For example, something like this:
#include <iostream>
class DefaultCtx {
private:
DefaultCtx() {};
const char *str = "default";
public:
static const char* get()
{
static DefaultCtx instance;
return instance.str;
}
DefaultCtx(DefaultCtx const &) = delete;
void operator=(DefaultCtx const &) = delete;
};
// Context for 64bits.
class Ctx64 {
private:
Ctx64() {};
const char *str = "64";
public:
static const char* get()
{
static Ctx64 instance;
return instance.str;
}
Ctx64(Ctx64 const &) = delete;
void operator=(Ctx64 const &) = delete;
};
template<typename Ctx>
class UsesCtx {
public:
UsesCtx() { std::cout << "Constructed using singleton " << Ctx::get() << std::endl; }
};
This scheme works fine, and I'm quite happy with the need to pass context as template parameter when constructing my objects. However, since Ctx64 is used for 64 bits representation, I wanted to add a little syntaxic sugar and use UsesCtx<64> :
int main() {
UsesCtx<DefaultCtx> a;
UsesCtx<Ctx64> b;
// UsesCtx<64> c; //< I don't know how to achieve that.
}
As I noted here, I don't know how to achieve it. I tried to redefine the class with an integer template, but that gives me the following error (compiled with g++ example.cpp --std=c++14)
// Gives compile error "error: template parameter ‘class Ctx’ redeclared here as ‘int n’"
template<int n>
class UsesCtx {
public:
UsesCtx() { std::cout << "Constructed using singleton " << n << std::endl; }
};
Is there any way I can have my class UsesCtx with both a class template parameter and an int template parameter? Of course, I can always instantiate with UsesCtx<Ctx64>, so this is not vital. But it didn't expected it to be hard to do.

Two otherwise identical functions (one uses Template Pattern, other doesn't)

#include <iostream>
void doSomething (int x) {std::cout << "Do something with " << x << std::endl;}
struct Base {
virtual int foo() const {return 5;}
virtual int goo() const {return 6;}
virtual int hoo() const {return 7;}
void noTemplatePattern() const {
// Code A
if (Base::foo() < 6) {
// Code B
}
doSomething (Base::goo());
// Code C
if (Base::hoo() > 10) {
// Code D
}
}
void templatePattern() const {
// Code A
if (foo() < 6) {
// Code B
}
doSomething (goo());
// Code C
if (hoo() > 10) {
// Code D
}
}
};
struct Derived : Base {
virtual int foo() const override {return 12;}
virtual int goo() const override {return 13;}
virtual int hoo() const override {return 14;}
};
int main() {
Derived d;
d.noTemplatePattern();
d.templatePattern();
}
How best to avoid repeating the codes contained in Code A, Code B, Code C, Code D, etc... other than creating helper functions for each? Is there a more generic way? I have functions that are identical except one uses the Template Pattern, and the other doesn't. The body of code between the virtual functions are identical. If I define a helper function for each identical part, it gets really messy, and there will be too many of them too.
In case you want more clarification, here is a snippet of my production code illustrating this. SpellCaster is derived from LivingBeing, and LivingBeing::cannotAttackLongRange(int) is overridden by SpellCaster::cannotAttackLongRange(int).
inline std::set<LivingBeingProxy*> LivingBeing::unattackableTargets() const {
std::set<LivingBeingProxy*> nonTargets;
if (isCharmed()) {
for (auto it = std::next(getStatesList(CHARM_SPELL).begin(), 1); it != getStatesList(CHARM_SPELL).end(); ++it)
nonTargets.emplace (std::dynamic_pointer_cast<CharmedStateBase>(*it)->getCharmer());
}
for (LivingBeingProxy* x : getLocation()->allBeingsAlive()) {
if ( (x->heightAboveGround() > damageInflictor(0)->getReach()) && !canFly()
&& LivingBeing::cannotAttackLongRange(distanceBetween(this, x->getActual()))) //*** virtual method here!
{nonTargets.emplace(x); continue;}
if ( (x->heightAboveGround()) < 0 && (x->getTerrain() == InWater) && !canSwim() )
{nonTargets.emplace(x); continue;}
}
// ...
return nonTargets;
}
inline std::set<LivingBeingProxy*> LivingBeing::unattackableTargetsIncludingBySpells() const {
std::set<LivingBeingProxy*> nonTargets;
if (isCharmed()) {
for (auto it = std::next(getStatesList(CHARM_SPELL).begin(), 1); it != getStatesList(CHARM_SPELL).end(); ++it)
nonTargets.emplace (std::dynamic_pointer_cast<CharmedStateBase>(*it)->getCharmer());
}
for (LivingBeingProxy* x : getLocation()->allBeingsAlive()) {
if ( (x->heightAboveGround() > damageInflictor(0)->getReach()) && !canFly()
&& cannotAttackLongRange (distanceBetween(this, x->getActual()))) //*** virtual method here!
{nonTargets.emplace(x); continue;}
if ( (x->heightAboveGround()) < 0 && (x->getTerrain() == InWater) && !canSwim() )
{nonTargets.emplace(x); continue;}
}
// ...
return nonTargets;
}
LivingBeing::unattackableTargets() computes all enemies that are not attackable by ordinary weapons, while LivingBeing::unattackableTargetsIncludingBySpells() computes all enemies that are not attackable by ordinary weapons and spells. A SpellCaster will want to call the first when attacking with an ordinary weapon, and will want to call the second when attacking with a spell.
With template and CRTP, if appropriate, you may do something like:
template <typename T, typename D>
void helper(const D& base)
{
// Code A
if (base.T::foo() < 6) {
// Code B
}
doSomething (base.T::goo());
// Code C
if (base.T::hoo() > 10) {
// Code D
}
}
struct Base {
virtual ~Base() = default;
virtual int foo() const {return 5;}
virtual int goo() const {return 6;}
virtual int hoo() const {return 7;}
void noTemplatePattern() const
{
// use Base::foo, Base::goo and Base::hoo
helper<Base>(*this);
}
#if 0
virtual void templatePattern() const = 0;
#endif
};
template <typename Derived>
struct BaseImpl : Base {
template <typename Derived>
void BaseImpl<Derived>::templatePattern() const {
// use Derived::foo, Derived::goo and Derived::hoo
helper<Derived>(static_cast<const Derived&>(*this));
}
};
Live example
If templatePattern / noTemplatePattern are long and complicated and boo, goo and hoo are simple, you could do the following:
struct Base {
virtual int foo(bool = false) const {return 5;}
virtual int goo(bool = false) const {return 6;}
virtual int hoo(bool = false) const {return 7;}
void Pattern(bool base) const {
// Code A
if (foo(base) < 6) {
// Code B
}
doSomething (goo(base));
// Code C
if (hoo(base) > 10) {
// Code D
}
}
};
struct Derived : Base {
int foo(bool base = false) const override {return base ? Base::foo() : 12;}
int goo(bool base = false) const override {return base ? Base::goo() : 13;}
int hoo(bool base = false) const override {return base ? Base::hoo() : 14;}
};
int main() {
Derived d;
d.Pattern(true); // d.noTemplatePattern();
d.Pattern(false); // d.templatePattern();
}
Not exactly elegant, but might work in a particular situation.
NB: If you use override keyword, you don't need to repeat virtual keyword.
One solution with Tag dispatching (but require more code for foo, goo, hoo)
struct Base {
virtual int foo() const {return foo(std::false_type());}
virtual int goo() const {return goo(std::false_type());}
virtual int hoo() const {return hoo(std::false_type());}
void noTemplatePattern() const { doIt (std::false_type()); }
void templatePattern() const { doIt (std::true_type()); }
private:
template <typename T>
void doIt (T t) const {
// Code A
if (foo(t) < 6) {
// Code B
}
doSomething (goo(t));
// Code C
if (hoo(t) > 10) {
// Code D
}
}
// tag dispatching between virtual call and Base::call
int foo(std::false_type) const {return 5;}
int goo(std::false_type) const {return 6;}
int hoo(std::false_type) const {return 7;}
int foo(std::true_type) const {return foo();}
int goo(std::true_type) const {return goo();}
int hoo(std::true_type) const {return hoo();}
};
Live example
Ok, this is one solution I thought of, but though it works I don't know if it is considered any good (need some opinions). But at least all repeated code is avoided, and thus any changes to those parts needs only be made once:
#include <iostream>
void doSomething (int x) {std::cout << "Do something with " << x << std::endl;}
struct Base {
virtual int foo() const {return fooBase();}
virtual int goo() const {return gooBase();}
virtual int hoo() const {return hooBase();}
virtual void voidFunction() const {voidFunctionBase();}
void noTemplatePattern() const {
doIt (&Base::fooBase, &Base::gooBase, &Base::hooBase, &Base::voidFunctionBase);
}
void templatePattern() const {
doIt (&Base::foo, &Base::goo, &Base::hoo, &Base::voidFunction);
}
private:
void doIt (int(Base::*a)()const, int(Base::*b)()const, int(Base::*c)()const,
void(Base::*d)()const) const {
// Code A
if ((this->*a)() < 6) {
// Code B
}
doSomething((this->*b)());
// Code C
if ((this->*c)() > 10) {
// Code D
}
(this->*d)();
// Code E
}
int fooBase() const {return 5;}
int gooBase() const {return 6;}
int hooBase() const {return 7;}
void voidFunctionBase() const {std::cout << "Base::voidFunction() called.\n";}
};
struct Derived : Base {
virtual int foo() const override {return 12;}
virtual int goo() const override {return 13;}
virtual int hoo() const override {return 14;}
virtual void voidFunction() const override {std::cout << "Derived::voidFunction() called.\n";}
};
int main() {
Derived d;
d.noTemplatePattern();
d.templatePattern();
}
Output:
Do something with 6
Base::voidFunction() called.
Do something with 13
Derived::voidFunction() called.
Opinions? A better solution?
A possibility, if applicable, is to slice your object:
void noTemplatePattern() const {
// copy only Base part (slicing). Require that Base is constructible
Base(*this).templatePattern();
}
Live example
There is a pretty easy, no-nonsense solution for this: Just replace the two functions by one which takes a parameter bool includeSpells. Then you can just check for this parameter in the function and execute the appropriate function call. The rest of the function remains unchanged.

Equal operator: pointer to a member function

In one of my classes I included a pointer to a member function:
private:
void (class_name::*_pf)(double&, gc::mag::coefficient&, gc::mag::st&, const int&) const;
This pointer either points to function1 or function2 of class class_name.
Now when I have two object of class class_name, how can I check whether the _pf pointers are pointing to the same member function (that is, are they both pointing at function1 or function2)?
This should be enough:
if (this->_pf == other._pf)
Example :
#include <iostream>
class class_name
{
public:
void function1(int) {}
void function2(int) {}
};
class test
{
public:
test(void (class_name::*pf)(int))
: _pf(pf)
{
}
bool operator==(const test& other)
{
return (this->_pf == other._pf);
}
public:
void (class_name::*_pf)(int);
};
int main()
{
test t(&class_name::function1);
test t2(&class_name::function2);
std::cout << std::boolalpha << (t == t2) << std::endl;
return 0;
}

Call different versions of template member function based on template paramaters

I need to call different versions of a template member function with the same arguments based on certain static members of the template parameters. Here's a sort of simplified version of what I need to do:
class A {
public:
//...
static const char fooString[];
};
const char A::fooString[] = "This is a Foo.";
class B {
public:
//...
static const char barString[];
};
const char B::barString[] = "This is a Bar.";
class C {
public:
//...
static const char fooString[];
};
const char C::fooString[] = "This is also a Foo.";
//Many other classes which have either a fooString or a barString
void doFoo(const char*s) { /*something*/ }
void doBar(const char*s) { /*something else*/ }
template&ltclass T>
class Something {
public:
//This version should be called if T has a static member called "fooString",
//so it should be called if T is either class A or C
void doSomething() { doFoo(T::fooString); }
//This version should be called if T has a static member called "barString",
//so it should be called if T is class B
void doSomething() { doBar(T::barString); }
};
void someFunc()
{
Something&ltA> a;
Something&ltB> b;
Something&ltC> c;
a.doSomething(); //should call doFoo(A::fooString)
b.doSomething(); //should call doBar(B::barString)
c.doSomething(); //should call doFoo(C::fooString)
}
How would I achieve this?
A possible solution:
#include <iostream>
#include <type_traits>
class A {
public:
//...
static const char fooString[];
};
const char A::fooString[] = "This is a Foo.";
class B {
public:
//...
static const char barString[];
};
const char B::barString[] = "This is a Bar.";
class C {
public:
//...
static const char fooString[];
};
const char C::fooString[] = "This is also a Foo.";
void doFoo(const char*s) { std::cout << "doFoo: " << s << "\n"; }
void doBar(const char*s) { std::cout << "doBar: " << s << "\n"; }
template<class T>
class Something {
public:
//This version should be called if T has a static member called "fooString",
//so it should be called if T is either class A or C
template <typename TT = T, typename std::enable_if<TT::fooString != 0, bool>::type = false>
void doSomething() { doFoo(T::fooString); }
//This version should be called if T has a static member called "barString",
//so it should be called if T is class B
template <typename TT = T, typename std::enable_if<TT::barString != 0, bool>::type = false>
void doSomething() { doBar(T::barString); }
};
int main()
{
Something<A> a;
Something<B> b;
Something<C> c;
a.doSomething(); //should call doFoo(A::fooString)
b.doSomething(); //should call doBar(B::barString)
c.doSomething(); //should call doFoo(C::fooString)
}
Output:
doFoo: This is a Foo.
doBar: This is a Bar.
doFoo: This is also a Foo.