I need something like "using Base::*;" - c++

If my base class has a function func(int) and my derived class has a function func(double), the derived func(double) hides base::func(int). I can use using to bring the base version into the derive's list of overloads:
struct base
{
void func(int);
};
struct derived : base
{
using base::func;
void func(double);
}
OK, great. But what if I'm not sure whether base has a func() or not? ie because I am doing template metaprogramming, I'm not actually sure what base is, but I want to bring its functions up to the same level - if they exist. ie change the above example to:
struct base_with
{
void func(int);
};
struct base_without
{
};
template <typename Base>
struct derived : Base
{
using Base::func; // if Base has a func(), I want to bring it in
void func(double);
}
derived<base_with> testwith; // compiles
derived<base_without> testwithout; // fails :-(
I need using_if like boost::enable_if. Doesn't seem possible...
Thanks in advance.

Since you're willing to put using statements into your derived class, I assume you know beforehands which members you may be interested to bring in. You can do this using boost::enable_if:
struct base_with
{
void func(int) { cout << "func(int)" << endl; }
};
struct base_without { };
// Custom traits, by default assume func() isn't present
template <class T> struct has_func : public boost::false_type { };
template<> struct has_func<base_with> : public boost::true_type { };
// Again, if nothing else is known, assume absence of func(int)
template <typename Base, class UseFunc = void> struct derived : Base
{
derived() { cout << "ctor: derived without" << endl; }
void func(double) { cout << "func(double)" << endl; }
};
// Derived with func(int)
template <typename Base> struct derived<Base, typename boost::enable_if< has_func<Base> >::type> : Base
{
using Base::func;
derived() { cout << "ctor: derived with" << endl; }
void func(double) { cout << "func(double)" << endl; }
};
Sorry for all the printing statements. Now if you try
derived<base_with> testwith;
derived<base_without> testwithout;
testwith.func(10);
testwith.func(10.5);
testwithout.func(10);
testwithout.func(10.5);
you should see
ctor: derived with
ctor: derived without
func(int)
func(double)
func(double)
func(double)
Obviously, this is going to get monstrous if you try to test for several features. If I was doing such mixin-style programming, I'd probably rather use functions with different names for different features so they wouldn't hide each other - then public inheritance would be all that is needed. Interesting question in any case.

I guess I need to do something like
struct dummy_func
{
private:
struct dumb_type {};
// interesting: does this need to be public?
public:
// use a type that no one can see, so func is never chosen by ADT
// and vararg just for paranoia
void func(dumb_type, dumb_type, dumb_type,...) { };
};
...
template <typename T>
struct has_func
{
enum { value = /* insert metaprogramming magic that checks for T::func */ }
};
template <typename Base>
struct derived : Base
{
using enable_if<has_func<Base>, Base, dummy_func>::type::func;
...
};
grrr. Of course this doesn't work because dummy_func is not a base of derived. In my case I could maybe make it derive from it when necessary. But still barely satisfactory.

Related

c++ 20 concepts in derived template class

for my test about CRTP I created this base class:
template<typename Derived>
struct Base
{
void print() const { std::cout << "print\n"; }
};
And this class:
struct A: public Base<A>
{
void printSub() { std::cout << "printSub from A\n"; }
};
And I can use these classes without problem:
A a1{};
a1.print();
a1.printSub();
My problem is: how is possible to use concept/requires for template class?
I want add something like this:
template<typename Derived> requires requires (Derived t) {
t.printSub();
}
struct Base
{
void print() { std::cout << "print\n"; }
};
To accept only Derived class with printSub method. But I receive this error:
template constraint failure...
I did some tests but I did not find solutions (I also found this thread but it can't help me).
Where am I wrong? Thanks for any help
You cannot meaningfully constrain the derived class template parameters of a CRTP base class for the same reason that you can't do this:
template<typename Derived>
class Base
{
using alias = Derived::SomeAlias;
};
Derived isn't complete yet, and using a constraint usually requires completeness.

Use base class implementation when base is template type

I have a class that receives its base type as a template arg and I want my derived class to call a function, print. This function should use the derived implementation by default but if the base class has a print function it should use the base implementation.
#include <iostream>
class BaseWithPrint {
public:
static void print(int i) { std::cout << "Base::print\n"; }
};
class BaseWithoutPrint {
};
template <typename B>
class Derived : public B {
public:
static void print(bool b) { std::cout << "Derived::bool_print\n"; }
template <typename T>
static void print(T t) { std::cout << "Derived::print\n"; }
void Foo() {
print(1);
print(true);
print("foo");
}
};
int main()
{
Derived<BaseWithPrint> d1;
d1.Foo();
Derived<BaseWithoutPrint> d2;
d2.Foo();
return 0;
}
This code only ever calls the Derived version of print.
Code can be seen at
https://onlinegdb.com/N2IKgp0FY
If you know that the base class will have some kind of print, then you can add using B::print to your derived class. If a perfect match isn't found in the derived, then it'll check the base.
Demo
To handle it for the case where there may be a base print, I think you need to resort to SFINAE. The best SFINAE approach is really going to depend on your real world situation. Here's how I solved your example problem:
template <class T, class = void>
struct if_no_print_add_an_unusable_one : T {
// only ever called if derived calls with no args and neither
// the derived class nor the parent classes had that print.
// ie. Maybe best to force a compile fail:
void print();
};
template <class T>
struct if_no_print_add_an_unusable_one <T, decltype(T().print(int()))> : T {};
//====================================================================
template <class B>
class Derived : public if_no_print_add_an_unusable_one<B> {
using Parent = if_no_print_add_an_unusable_one<B>;
using Parent::print;
public:
// ... same as before
};
Demo

Infer 'this' pointer type when called from derived class?

I have a method in a baseclass that needs the type passed to it for some type-related operations (lookup, size, and some method invocation). Currently it looks like this:
class base
{
template<typename T>
void BindType( T * t ); // do something with the type
};
class derived : public base
{
void foo() { do_some_work BindType( this ); }
};
class derivedOther : public base
{
void bar() { do_different_work... BindType( this ); }
};
However, I wonder if there's a way to get the caller's type without having to pass this so that my callpoint code becomes:
class derived : public base
{
void foo() { BindType(); }
};
Without the explicit this pointer. I know that I could supply the template parameters explicitly as BindType<derived>(), but is there a way to somehow extract the type of the caller in some other way?
There's no magical way to get the caller's type, but you can use CRTP (as a comment mentions) in order to automate this behavior, at the cost of a bit of code complexity:
class base
{
template<typename T>
void BindType(); // do something with the type
};
template <class T>
class crtper : base
{
void BindDerived { BindType<T>(); }
}
class derived : public crtper<derived>
{
void foo() { do_some_work BindDerived(); }
};
class derivedOther : public crtper<derivedOther>
{
void bar() { do_different_work... BindDerived(); }
};
Edit: I should mention, I would kind have expected that foo would be a virtual function, defined without implementation in base. That way you would be able to trigger the action directly from the interface. Although maybe you have that in your real code, but not in your example. In any case, this solution is perfectly compatible with this.
Edit2: After question edit, edited to clarify that solution still applies.
If you want to avoid BindType<derived>(), consider (a bit verbose, I agree) BindType<std::remove_reference<decltype(*this)>::type>(); to avoid passing a parameter. It gets resolved at compile-time and avoids run-time penalties.
class base
{
protected:
template<typename T>
void BindType() { cout << typeid(T).name() << endl; } // do something with the type
};
class derived : public base
{
public:
void foo()
{
BindType<std::remove_reference<decltype(*this)>::type>();
}
};
It will not work as you expect
The result of foo() might be different of what you expect:
class derived : public base // <= YOU ARE IN CLASS DERIVED
{
public:
void foo() { BindType( this ); } // <= SO this IS OF TYPE POINTER TO DERIVED
};
The template paramter is deducted at compile time, so that it will be derived*. If you would call foo() from a class derived_once_more derived from derived, it would still use the type derived*.
Online demo
But you can get rid of the dummy parameter*
You may use decltype(this) to represent the typename of a variable. It's still defined at compile time:
class base
{
public:
template<typename T>
void BindType( )
{
cout << typeid(T*).name()<<endl; // just to show the type
}
virtual ~base() {}; // for typeid() to work
};
class derived : public base
{
public:
void foo() { BindType<decltype(this)>( ); }
};
Online demo
Edit: other alternatives
As template parameters need to be provided at compile-time and not a run time, you can use:
template parameter deduction (your first code snippet)
decltype (see above)
if you intend to add this in all the derived classes you could use a macro to get it done, using one of the above mentionned solution
you could use the CRTP pattern (already explained in another answer).
A possible solution that avoids the intermediate class of the CRTP follows:
class base {
using func_t = void(*)(void *);
template<typename T>
static void proto(void *ptr) {
T *t = static_cast<T*>(ptr);
(void)t;
// do whatever you want...
}
protected:
inline void bindType() {
func(this);
}
public:
template<typename T>
base(T *): func{&proto<T>} {}
private:
func_t func;
};
struct derived1: base {
derived1(): base{this} {}
void foo() {
// ...
bindType();
}
};
struct derived2: base {
derived2(): base{this} {}
void bar() {
// ...
bindType();
}
};
int main() {
derived1 d1;
d1.foo();
derived2 d2;
d2.bar();
}
The basic idea is to exploit the fact that the this pointers in the constructor of the derived classes are of the desired types.
They can be passed as a parameter of the constructor of the base class and used to specialize a function template that do the dirty job behind the hood.
The type of the derived class is actually erased in the base class once the constructor returns. Anyway, the specialization of proto contains that information and it can cast the this pointer of the base class to the right type.
This works fine as long as there are few functions to be specialized.
In this case there is only one function, so it applies to the problem pretty well.
You can add a static_assert to add a constraint on T, as an example:
template<typename T>
base(T *t): func{&proto<T>} {
static_assert(std::is_base_of<base, T>::value, "!");
}
It requires to include the <type_traits> header.

How to declare a template method of a template base class using 'using'?

Two methods for accessing template base class members are described here. When the base class member itself is a template, accessing it using the first method (this->) above is described here. Is there a way to use the second method (using xxxx) in this scenario as well?
For example, in the code below, is it possible to replace "????" with something to make the code work?
using namespace std;
template<typename T> class base
{
public:
template<bool good> void foo()
{
cout << "base::foo<" << boolalpha << good << ">()" << endl;
}
};
template<typename T> class derived : public base<T>
{
public:
using ????
void bar()
{
foo<true>();
}
};
Just for the record, even though it does not provide any answer or workaround, but I am currently working with VS Express 2013, and I can assure you that
#include <iostream>
template<typename T> class base
{
public:
template<bool good> void foo()
{
std::cout << "base::foo<" << good << ">()" << std::endl;
}
};
template<typename T> class derived : public base<T>
{
public:
void bar()
{
foo<true>();
}
};
struct A{};
void main() {
derived<A> a;
a.bar();
}
works perfectly fine...

Disable method override in template derived class

Would it be possible to disable the Foo() override in the derived class (by means of std::enable_if or some boost magic), in case T is not of a certain type, without having to write a template specialization for class Derived?
Bonus points: could the override be disabled if T does not define a certain method?
Here is my SSCCE:
#include <iostream>
#include <string>
class Base
{
public:
virtual std::string Foo()
{
return "Base";
}
};
template <typename T>
class Derived : public Base
{
public:
virtual std::string Foo() override
{
return "Derived";
}
};
int main()
{
Derived<int> testInt;
std::cout << testInt.Foo() << std::endl;
Derived<float> testFloat;
std::cout << testFloat.Foo() << std::endl;//I would like this to print 'Base'
}
UPDATE:
Thank you for the wonderful solutions, but I wasn't able to adapt them to my real code. The following example should provide a better idea of what I'm trying to achieve:
#include <iostream>
#include <string>
class Object
{
public:
void Test()
{
std::cout << "Test" << std::endl;
}
};
class EmptyObject
{
};
class Base
{
public:
virtual std::string Foo()
{
return "Base";
}
};
template <typename T>
class Derived : public Base
{
public:
virtual std::string Foo() override
{
m_object.Test();
return "Derived";
}
private:
T m_object;
};
int main()
{
Derived<Object> testObject;
std::cout << testObject.Foo() << std::endl;
Derived<EmptyObject> testEmpty;
std::cout << testEmpty.Foo() << std::endl;
}
I would do this by creating two functions that Derived::Foo can delegate to conditionally based on whether T = float. One would contain the real Derived::Foo implementation, while the other would call Base::Foo.
template <typename T>
class Derived : public Base
{
public:
virtual std::string Foo() override
{
return do_Foo(std::is_same<T, float>{});
}
private:
std::string do_Foo(std::false_type)
{
return "Derived";
}
std::string do_Foo(std::true_type)
{
return Base::Foo();
}
};
Live demo
It seems what you actually want to do is call the Derived<T>::Foo() implementation only if T defines a certain member function, otherwise Base::Foo() should be called. This can be done using expression SFINAE.
template <typename T>
class Derived : public Base
{
public:
std::string Foo() override
{
return do_Foo(true);
}
private:
template<typename U = T>
auto do_Foo(bool)
-> decltype(std::declval<U>().test(), void(), std::string())
{
return "Derived";
}
std::string do_Foo(int)
{
return Base::Foo();
}
};
Live demo
In the code above, if the type T does not define a member function named test(), the do_Foo(bool) member function template will not be viable. On the other hand, if T::test() does exist, then do_Foo(bool) will be selected because the boolean value being passed to do_Foo by Foo makes it a better match as compared to do_Foo(int).
A detailed explanation of what's going on within the decltype expression in the trailing return type can be found here.
Instead of template specialize the class, you may template specialize the method directly: (https://ideone.com/gYwt5r)
template<> std::string Derived<float>::Foo() { return Base::Foo(); }
And I only see template specialization of a class to disable future override depending of T by adding final to the virtual method.
If you need to restrict a certain type at compile time, you can use std::enable_if together with std::is_same :
typename std::enable_if<std::is_same<T, float>::value, std::string>::type
virtual Foo() override
{
return "Derived";
}
Or you can easily redirect the call to the Base method if the template type is not the type you are looking for, still with std::is_same :
virtual std::string Foo() override
{
return std::is_same<T, float>::value ? Base::Foo() : "Derived";
}
As for the Bonus, you can get the trait from this SO answer, adapted here with decltype, for a method bar() :
template <typename T>
class has_bar
{
typedef char one;
typedef long two;
template <typename C> static one test(decltype(&C::bar) ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
The limitation is that you can't put constraints on the arguments or return types.
virtual std::string Foo() override
{
return has_bar<T>::value ? "Derived" : Base::Foo() ;
}
Note:
You could also use has_bar together with enable_if as in my first example, to disable it a compile time.
You can add an intermediate class to your hierarchy:
class Base
{
public:
virtual std::string Foo()
{
return "Base";
}
};
template <typename T>
class Intermediate : public Base
{
// common operations with m_object
protected: // not private!
T m_object;
};
template <typename T, typename = bool>
class Derived : public Intermediate<T> {};
template <typename T>
class Derived<T, decltype(std::declval<T>().Test(), void(), true)>
: public Intermediate<T>
{
public:
virtual std::string Foo() override
{
this->m_object.Test(); // this-> is necessary here!
return "Derived";
}
};
The full example compiles successfully with both clang 3.4 and g++ 4.8.2.