I have classes A1, A2, and B:
struct A1 { int call(int); };
struct A2 { double call(double); };
struct B : public A1, public A2 {};
Due to the name 'call' being shared by A1 and A2, the compiler hides those names in B, even if the signatures aren't the same.
struct B { void do_stuff() { call(int(0)); /* call? call what? *ERROR* */ } };
So then I go ahead and throw down some using declarations:
struct B { using A1::call; using A2::call; void do_stuff() { call(int(0)); } };
And everything's hunky-dory. But what if A1 and A2 have a lot of similarly named members, ex. A1 and A2 are specializations for some template class, and we want B to have the members of both under one roof? Then it ends up looking... well, very boilerplate heavy.
struct B {
using A1::call; using A2::call;
using A1::asdf; using A2::asdf;
using A1::other_thing; using A2::other_thing;
...
};
I have to do this kind of a thing for tens of classes inheriting from lower-level class specializations. Is there any construct that would ease this keyboard tip-tappin' and readability hell?
Something like using A1::* if using declarations somehow supported globbing.
Update:
I've come up with a solution that recursively places using-declarations in a pseudo-variadic template hierarchy. It actually comes out really clean looking in the client code, looking something like this:
class B : mixins<A1,A2> {
void do_stuff() {
call(int(0)); // I'm not a compiler error!
call(double(0)); // neither am I!
}
};
I'll post the details as an answer if no one else comes up with anything.
Related
What I'm trying to do is to have a base class that has a primary functionality, as well as multiple derived classes that have various other additional functions/variables. The main functionality of all these derived classes will behave very similarly no matter what object of one of the derived classes is passed to it, but with slight changes based on what the derived class is.
So a background here is that I'm mostly experienced with Fortran programming but am trying to break into C++ more. I'm trying to do something here that is pretty easy in Fortran but am having trouble in C++. Basically my code defining my classes looks something like this
class base_class{
public:
void prim_func(base_class &my_obj);
};
class derived_class_1: public base_class{
public:
int a_func(int arg1);
};
class derived_class_2: public base_class{
public:
double a_func(double arg2);
};
And then the void class method looks something like (right now, I know this isn't right)
void base_class::prim_func(base_class &my_obj){
// a bunch of stuff for all classes
// if my_obj class is derived_class_1
my_obj.a_func(1);
// some more stuff specific to using derived_class_1
// if my_obj class is derived_class_2
my_obj.a_func(1.5);
// some more stuff specific to using derived_class_2
// a bunch of stuff for all classes
}
I want that prim_func to have (slightly) different behaviors based on what the actual derived class that is passed to it is. So the main code would look like this
derived_class_1 def_obj_1;
derived_class_2 def_obj_2;
main(){
def_obj_1.prim_func(def_obj_1);
def_obj_2.prim_func(def_obj_2);
}
So I would like to slightly modify the behavior in this primary functionality based on what the derived class of the passed object actually is. In Fortran there is a SELECT TYPE functionality (https://www.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/language-reference/a-to-z-reference/s-1/select-type.html) that allows this, but I can't seem to find something similar in C++?
I know one workaround could be to just make one big class that contains overloaded versions of all the different functions, and all the different variables that the various derived class objects would need, and then just have an indicator variable to let it know which functionality it should be using. But this would be extremely inelegant and would potentially cause some other issues, so I would like to avoid it.
You can't do that with plain C++.
You can't have derived classes with overriden functions with different signatures.
What you can do is using templates.
Use a templated Base Class that provides the base function as a pure virtual.
You can then write a wrapper around that function as a template:
template<typename T>
class Base {
public:
virtual T func(T param) = 0;
};
class DerivedA : public Base<int> {
public:
int func(int param) override {
return param;
};
};
class DerivedB : public Base<double> {
public:
double func(double param) override {
return param;
};
};
template<typename T>
T prim_func(Base<T>& base, T param) {
return base.func(param);
}
int main() {
DerivedA a;
DerivedB b;
auto c = prim_func(a,4);
auto d = prim_func(b,4.0);
}
Ok, so it turns out there is a way to do this in C++ it just involves dynamic casting a pointer using the passed object (but it does have to be a polymorphic object). So the way I made it work was doing something like this (comparing to the previous incomplete code I had).
class base_class{
public:
virtual void a_func(){};
void prim_func(base_class &my_obj);
};
class derived_class_1: public base_class{
public:
int a_func(int arg1);
};
class derived_class_2: public base_class{
public:
double a_func(double arg2);
};
void base_class::prim_func(base_class &my_obj){
// a bunch of stuff for all classes
if(derived_class_1* class_ptr = dynamic_cast<derived_class_1*>(&my_obj)){
class_ptr.a_func(1);
// some more stuff specific to using derived_class_1
}
else if(derived_class_2* class_ptr = dynamic_cast<derived_class_2*>(&my_obj)){
class_ptr.a_func(1.5);
// some more stuff specific to using derived_class_2
}
// a bunch of stuff for all classes
}
derived_class_1 def_obj_1;
derived_class_2 def_obj_2;
main(){
def_obj_1.prim_func(def_obj_1);
def_obj_2.prim_func(def_obj_2);
}
To be clear, this still won't compile/work since some of the functions need definitions and what not, but this is a general description of how to do it. A working example can be found in MFEM's code here: https://docs.mfem.org/4.5/amgxsolver_8cpp_source.html#l00859
Given a class, I would like to find the largest sizeof() all child classes of it in compile-time. In this case, you will need to properly define the value of B::BIGGEST_TYPE_SIZE, preferably in the class itself.
It is possible to do so in a separate chunk of code with the usage of std::max() as shown in the last line, but it's some what duplicate code and unelegant, as I will have to continuously modify that line as more classes inherit from B.
I would like a nice scalable solution instead.
struct B
{
static const int BIGGEST_TYPE_SIZE;
};
struct D1 : public B
{
int i;
};
struct D2 : public B
{
std::vector<int> vec;
};
struct D3 : public B
{
std::string s;
};
const int B::BIGGEST_TYPE_SIZE = std::max(sizeof(D1), std::max(sizeof(D2), sizeof(D3)));
The value of BIGGEST_TYPE_SIZE should be "32", due to std::string.
Any elegant solutions for this?
The sexier the templates, the better.
Thanks!
Take for example std::variant, it knows its size from the template arguments. Your best shot is also to use a variadic template. First, you implement the variadic max function template, then you use it:
template <typename ... Ts>
constexpr bool biggest_size_v = max(sizeof(Ts)...);
If you're asking to automatically get a list of all derived classes at compile-time. You can't. You still have to list them:
const int B::BIGGEST_TYPE_SIZE = biggest_size_v<D1, D2, D3>;
It is possible to do so in a separate chunk of code with the usage of std::max as shown in the last line, but it's some what duplicate code and unelegant, as I will have to continuously modify that line as more classes inherit from B.
I would like a nice scalable solution instead.
Unfortunately, I don't know a way to automatically know all derived types (I don't think it's possible) so I fear that you needs "to continuously modify that line as more classes inherit form B".
In LogicStuff's answer you see an elegant way to simplify that line and I also remember that exist the std::max() version that receive a std::initializer_list (constexpr starting from C++14) so you can also write (but the biggest_size_v way is better, IMHO)
const int B::BIGGEST_TYPE_SIZE
= std::max({sizeof(D1), sizeof(D2), sizeof(D3)});
avoiding the multiple std::max() calls.
A little off topic, I suppose, but I propose you a semi-automatic way to check, compile-time, that B::BIGGEST_TYPE_SIZE is bigger (or equal) to the sizeof() of all derived types (all instantiated derived type, at least).
If you modify B adding a constructor with a static_assert() in it (or SFINAE enabled, if you prefer)
struct B
{
static const int BIGGEST_TYPE_SIZE;
template <std::size_t DerSize>
B (std::integral_constant<std::size_t, DerSize>)
{ static_assert( DerSize <= BIGGEST_TYPE_SIZE, "!" ); }
};
and add a template C struct that inherit from B
template <typename Der>
struct C : public B
{
C() : B{std::integral_constant<std::size_t, sizeof(Der)>{}}
{ }
};
if you modify your Dx classes to inheriting B passing through C<Dx> (so using CRTP)
struct D1 : public C<D1>
{ int i; };
struct D2 : public C<D2>
{ std::vector<int> vec; };
struct D3 : public C<D3>
{ std::string s; };
you auto-magically enable the compile-time check inside B constructor.
So if you add, by example, the following D4 class
struct D4 : public C<D4>
{ int a[42]; };
and forget to modify the BIGGEST_TYPE_SIZE initialization adding sizeof(D4) in the list, declaring a D4 object you get a compilation error
D4 d4; // compilation error
The following is a full compiling example
#include <vector>
#include <iostream>
#include <algorithm>
struct B
{
static const int BIGGEST_TYPE_SIZE;
template <std::size_t DerSize>
B (std::integral_constant<std::size_t, DerSize>)
{ static_assert( DerSize <= BIGGEST_TYPE_SIZE, "!" ); }
};
template <typename Der>
struct C : public B
{
C() : B{std::integral_constant<std::size_t, sizeof(Der)>{}}
{ }
};
struct D1 : public C<D1>
{ int i; };
struct D2 : public C<D2>
{ std::vector<int> vec; };
struct D3 : public C<D3>
{ std::string s; };
struct D4 : public C<D4>
{ int a[42]; };
const int B::BIGGEST_TYPE_SIZE
= std::max({sizeof(D1), sizeof(D2), sizeof(D3)}); // <-- sizeof(D4) forgotten !!!
int main ()
{
D1 d1;
D2 d2;
D3 d3;
// D4 d4; compilation error
}
Sorry for my poor english I'll try to do my best.
I want to design an interface that should be used like this:
class MyObject : public IMyInterface<MyObject>
{
// ...
};
The interface could look like this:
template <class _TMyObject>
class IMyInterface
{
virtual _TMyObject* Get() = 0;
};
What i'm looking after, is a way to verify, at compile time, that the interface is used as intended.
How can I test if _TMyObject "is-a" IMyInterface<_TMyObject>? Inside the interface definition, with a static_assert for example.
Thanks for any help :).
Have a nice day!
You can't put static_assert inside the class itself, because D is an incomplete type, but you can put it in the destructor (or constructor, but there can be many constructors):
template<class D>
struct B
{
~B()
{
static_assert(std::is_base_of_v<B, D>);
};
};
struct Not_E {};
struct D : B<D> { };
struct E : B<Not_E> { };
void foo()
{
D d; // OK
E e; // Fails
}
Addition. Note that this solution is not a complete protection against incorrect usage of CRTP. Please refer to Some Programmer Dude's answer for a nice example of error that can't be caught by it.
Since C++11 there are many type property traits that could be used to do checks at compile-time.
For example std::is_base_of which in your case could be used like perhaps
template<typename TChild>
struct IMyInterface
{
static_assert(std::is_base_of<IMyInterface, TChild>::value, "Derived class not derived from IMyInterface");
// ...
};
Note: The exact code shown above will not work directly, but rather show the principle.
Of course, that do allow something like
class MyFirstClass : public IMyInterface<MyFirstClass>
{
// ...
};
// Note wrong class in template
// vvvvvvvvvvvv
class MySecondClass : public IMyInterface<MyFirstClass>
{
// ...
};
So to answer your question if it's possible for such a check: Not really the way you want. Even using other traits and meta-programming, you can never guarantee that the template argument for the interface class is "correct" when used in the CRTP.
The only way I can see it work is by using down-casting at run-time with dynamic_cast, something like dynamic_cast<TChild*>(this) != nullptr in the interface class.
Given some base interfaces A, B, C.... N
And some hypothetical classes which implement a set of them:
class MyClass1: public A, public B, public N;
class MyClass2: public A, public B, public D;
I would like to create function which accept as parameter an object (or pointer to object) to a class which include, lets say A and B.
void myFunc( A&B obj );
From a C++ programmer perspective, this seem absurd. From a software architect perspective, this seem like the basic bloc that all languages should have.
Is there any trick (except template) or solution for that?
Note: Most of the interfaces do not come from me, so it is (in principle) no possible to make changes on interfaces.
EDITED:
Here some example:
class A{
public:
virtual void draw()=0;
};
class B{
public:
virtual void edit()=0;
};
class AandB: public A, public B
{
virtual void draw()override{};
virtual void edit()override{};
};
//This function know about A, B, but not AandB
void some_function((A+B)& a_and_b) { // That do not work
a_and_b.draw();
a_and_b.edit();
}
int main()
{
AandB c;
some_function(c); // that is not so easy
}
#include <type_traits>
using namespace std;
class A{};
class B{};
template<class T, enable_if_t<is_same<A, decay_t<T>>::value || is_same<B, decay_t<T>>::value, int> = 0>
void some_function(T&& a_or_b) {}
live: https://godbolt.org/g/Z1MV8w
This example requires c++14, but you can use enable_if instead if you need 11 compatibility. It's just not as readable.
If you want to take anything that inherits from either A or B, use is_base_of instead of is_same
What you are really asking for is the compiler to create an intermediate type (A & B) whose interface contains both interface A and interface B. And then to allow any type that implements both those interfaces to bind to a reference of this combined type.
I am not even sure how you might refer to such a gestalt type in syntax:
void func((A+B)& var); // ???
Well you can do a similar thing with current syntax without the compiler creating scaffolding behind the scenes by simply accepting the parameter twice like this:
struct A { void stuff(){ std::cout << "A\n"; } };
struct B { void stuff(){ std::cout << "B\n"; } };
struct C { void stuff(){ std::cout << "C\n"; } };
struct MyType: A, B, C
{
void stuff() { std::cout << "MyType\n"; }
};
void func(A& a, B& b) // accept both interfaces in func
{
a.stuff(); // use interface A
b.stuff(); // use interface B
}
int main()
{
MyType m;
func(m, m); // pass both interfaces to func()
}
I voted on xaxxon answer,
but f you want to do it in "virtual" way,
you can do class that extends A and B.
Will look like this:
class A;
class B;
class A_B: public A, public B{
};
class MyClass1: public A_B, public XXX{
};
class MyClass2: public A_B, public YYY{
};
void myFunc( A_B obj );
I agree this looks suspiciously much like Java.
One way to mitigate cons of template
void myFunc_impl(A& aPart, B& bPart); // aPart and bPart are from the same object.
template <typename T>
void myFunc(T& obj) {
// static_assert to have better error messages
static_assert(std::is_base_of<A, T>::value, "T should inherit from A");
static_assert(std::is_base_of<B, T>::value, "T should inherit from B");
// Forwarding to implementation
myFunc_impl(obj, obj);
}
1) force definition to be in the header, difficult to maintain
You just have the forwarding in the header:
code is short.
2) difficult to manage with polymorphic pointers,
As long as you take reference or pointer, this part if ok with template.
4) It make difficult or impossible some other features like virtual?
Indeed, template method cannot be template, but here, you may forward to a virtual method.
5) Code is difficult to check, as issues are apparent only at usage stage.
You have indeed to instantiate it to see all errors.
I have a large set classes which I need to "wrap" in a very thin subclass. The functionality of the base classes doesn't change, and their interface remains intact.
The problem is, that in order to use the base classes's constructors (and most of them have more than one), I need to decalre an identical constructor in each of the subclasses, and simply pass the parameters over to the constructor of the base class (99% of the time I have nothing else to do upon construction). That's a lot of pointless work.
What's the easiest way to do this?
Edit: Even if it's not natively supported in the language, maybe there's some tool that can auto-generate that code?
You could add templated constructors for all possible parameters to your wrapper class:
template<class Base>
class wrapper : public Base {
public:
wrapper() : Base() {}
template<typename T1>
wrapper(T1 a1) : Base(a1) {}
template<typename T1, typename T2>
wrapper(T1 a1, T2 a2) : Base(a1, a2) {}
// ...
};
Since the templates will not be instantiated for constructors that aren't called it doesn't matter if these other constructors would be invalid. Only the constructors that are actually used need to exist in the base class:
class A {
public:
A(int a) {};
};
int main() {
wrapper<A> aw(1);
return 0;
}
Probably there are some corner cases where this approach will lead to problems, but for simple cases it works.
I think you're out of luck unless you can use C++0x. Read this article:
Automatic creation of constructor, based on parent class' constructor (C++)
Wishful thinking leads me to suggest
class BaseClass {
public:
BaseClass(foo, bar, baz);
};
template <class T>
class BaseInheritor : public BaseClass {
public:
T(foor, bar, baz);
};
class Child : public BaseInheritor<Child> {
// Other stuff
};
I don't think C++ templates can quite do what I've just written, unfortunately. There's a pretty straightforward answer with macros, but I feel dirty suggesting it:
#define CHILD_CLASS_DEFAULT(name) \
class name : public BaseClass { \
public: name(foo, bar, baz) : BaseClass(foo, bar, baz) { } \
private:
#define CHILD_CLASS_OVERRIDE(name) \
class name : public BaseClass { \
I'd go for a script-based solution, maybe based on gccxml or something similar.
With that you could write a simple script (i.e. generate-derivate <input-file> <base-name> <derivative-name> <output-file>) that generates you the wrapper. You'd only have to make changes manually if you are adding/changing functionality.
edit: vague outline:
write derivative-name + " : public " + base-name + " {\npublic:\n"
foreach <Constructor> where attribute name == base-name
write "\tderivate-name("
foreach <Argument>
resolve by attribute type (query FundamentalType, ReferenceType, ...)
write argument type etc.
write ");\n"
write "\n};\n"
It all depends on what script language and what xml tools you use. Trolltech has XQuerys in their example.