I have created an example to show the language features I am using, the real case is not as simple. The include file is included twice, once for each class. Even though the text is the same, the underlying types are different. In the real case some variables have more initialization than others depending on the class.
Working program
ex1.cpp
#include <iostream>
class one {
public:
one(int a1,int b1) : a(a1), b(b1) {}
int a,b;
#include "ex1.h"
};
class two {
public:
two(double a1,double b1) : a(a1), b(b1) {}
double a,b;
#include "ex1.h"
};
int main()
{
one c1(1,2);
two c2(3.4,5.7);
c1.f();
c2.f();
return 0;
}
ex1.h
void f()
{
std::cout << ( a + b ) << std::endl;
}
I was hoping to change this to a program that uses templates as follows, but I get a compile error.
ex2.cpp
#include <iostream>
class one {
public:
one(int a1,int b1) : a(a1), b(b1) {}
int a,b;
void f();
};
class two {
public:
two(double a1,double b1) : a(a1), b(b1) {}
double a,b;
void f();
};
template<typename X>
void X::f()
{
std::cout << ( a + b ) << std::endl;
}
int main()
{
one c1(1,2);
two c2(3.4,5.7);
c1.f();
c2.f();
return 0;
}
The error message is error: invalid use of template type parameter 'X'
I believe the correct way to do what you want is to use a template to handle the different types present in the class:
#include <iostream>
template<typename X>
class foo {
public:
foo(X a1, X b1) : a(a1), b(b1) {}
X a,b;
void f();
};
template<typename X>
void foo<X>::f()
{
std::cout << ( a + b ) << std::endl;
}
int main()
{
foo<int> c1(1,2);
foo<double> c2(3.4,5.7);
c1.f();
c2.f();
return 0;
}
Generally speaking you don't want to #include code directly into your class to remove code duplication, c++ gives you some better options.
You can see this run here: http://coliru.stacked-crooked.com/a/34d146d7feac8abd
CRTP to the rescue:
template<class D>
struct f_support {
void f() {
// does not block all errors, but catches some:
static_assert( std::is_base_of< f_support, D >::value, "CRTP failure" );
auto* dis = static_cast<D*>(this);
std::cout << ( dis->a + dis->b ) << std::endl;
}
};
then:
class one: public f_support<one> {
...
class two: public f_support<two> {
...
You could move the implementation of f_support<D> into a .cpp file, but that is a hassle.
I would like to thank #Yakk and #shuttle87 for their answers. I took the simplicity of shuttle87's answer and the flexibility of Yakk's answer to come up with this one. Without your help, I would still be using include files. The problem with my solution below is that it requires all classes to have the same number of arguments in their constructor.
#include <iostream>
class one {
public:
one(int a1,int b1) : a(a1), b(b1) {}
int a,b;
void g() { std::cout << "one\t"; }
};
class two {
public:
two(double a1,double b1) : a(a1), b(b1) {}
double a,b;
void g() { std::cout << "two\t"; }
};
template<class X, typename Y>
class three : public X {
public:
three(Y a, Y b) : X(a,b) {}
void f()
{
X::g();
std::cout << ( X::a + X::b ) << std::endl;
}
};
int main()
{
three<one,int> c1(1,2);
three<two,double> c2(3.4,5.7);
c1.f();
c2.f();
return 0;
}
Related
In case of a templeted class. How can I expose its static function (of all its instances) for everyone to use?
template < typename T >
class A {
public:
void set(T x, T y) {
a = x;
b = y;
}
T a, b;
};
.CPP file: I have some (static) A's (different types):
A<int> Ai();
A<char> Ac();
.H file : reason: I want a lot of classes to be able to set them all.
A<int>::Ai.set(int x, int y); // how do I do that?
A<char>::Ai.set(char x, char y) ;
How can I expose/allow others to use the set functionality of each of the A's?
I was thinking about wrapping each A with:
void SetAInt(...)
{
Ai.Set(...);
}
and exposing:
// .H file:
void SetAInt(...);
void SetAChar(..);
How can I do it without a wrapper?
Here is something that is probably close to what you are looking for:
template < typename T >
class A {
public:
static void set(T x, T y) {
a = x;
b = y;
}
static T a, b;
};
template<typename T>
T A<T>::a;
template<typename T>
T A<T>::b;
int main() {
A<int>::set(10, 20);
std::cout << A<int>::a << '\n';
std::cout << A<int>::b << '\n';
return 0;
}
Note: This design would never pass a review. (The code is correct...it's just that the design is broken)
Can boost variant safely accept pointers to classes that are forward declared without any unintended implications such as using them with visitors?
class A;
class B;
typedef boost::variant<A*, B*> Variant;
class A {
public:
A() {}
};
class B {
public:
B() {}
};
I'd suggest using the builtin recursive element support for this exact purpose. It makes the (de)allocation(s) automatic and exception safe.
Here's a complete demo where B actually recursively contains a vector<Variant> (which is 90% of the use-cases for forward-declared element types):
Live On Coliru
#include <boost/variant.hpp>
#include <iostream>
#include <iomanip>
struct A;
struct B;
typedef boost::variant<A, B> Variant;
struct A {
int solution = 42;
};
struct B {
std::string answer = "Thanks for all the fish!";
std::vector<Variant> other { A{1}, A{2}, B{"Three", {}}, A{4} };
};
struct Visitor {
std::string indent = " - ";
void operator()(Variant const& v) const {
boost::apply_visitor(Visitor{" " + indent}, v);
}
void operator()(A const& a) const { std::cout << indent << a.solution << "\n"; };
void operator()(B const& b) const {
std::cout << indent << std::quoted(b.answer) << "\n";
for (auto& v : b.other) {
operator()(v);
}
};
};
int main()
{
Variant v;
v = A{};
boost::apply_visitor(Visitor{}, v);
v = B{};
boost::apply_visitor(Visitor{}, v);
}
Prints
- 42
- "Thanks for all the fish!"
- 1
- 2
- "Three"
- 4
Here is the test code:
class A{};
class B : public A{};
void Test(const std::vector<A>& a)
{
}
int main()
{
std::vector<A> a;
std::vector<B> b;
Test(a);
Test(b);//Compiler Error
return 0;
}
Since std::vector<A> and std::vector<B> is different type, we can't make conversion from one to another.
An optional way can be:
class A{};
class B : public A{};
void Test(const std::vector<A>& a)
{
}
int main()
{
std::vector<A> a;
std::vector<B> b;
Test(a);
Test(std::vector<A>(b.begin(), b.end()));
return 0;
}
It acts, but it takes extra copying from B to A. If A or B is a large object, it can be very slow. A better choice is:
class A{};
class B : public A{};
void Test(const std::vector<A>& a)
{
}
int main()
{
std::vector<A> a;
std::vector<B> b;
Test(a);
Test(std::vector<A>(std::make_move_iterator(b.begin()), std::make_move_iterator(b.end())));
return 0;
}
Since it just move the iter instead of the whole B class, it take a better performance. But there are some extra cost - If b is a very large vector with huge number of items, iteration also can slow down my code.
So I wonder if there is a way to directly convert std::vector<B> to std::vector<A> without any extra cost?
One approach is to make the vector a template parameter of the Test function. The calling code will remain the same, there is no copying required.
#include <vector>
#include <iostream>
class A{
public:
virtual void print() const {
std::cout << "A" << std::endl;
}
};
class B : public A{
virtual void print() const {
std::cout << "B" << std::endl;
}
};
template <typename ContainerA>
void Test(const ContainerA& aas)
{
for(const A& a:aas) {
a.print();
}
}
int main()
{
std::vector<A> a;
a.push_back(A());
std::vector<B> b;
b.push_back(B());
Test(a);
Test(b);
return 0;
}
I don't know if it's useful for you but the best I can think is pass std::vector<Derived> to the function and iterate the element as Base elements.
Something like
template <typename D>
void Test (std::vector<D> const & v)
{
for ( A const & elem : v )
{
// use elem
}
}
Using SFINAE you can enable Test() only for vectors of Base or derived from Base elements as follows
template <typename D>
typename std::enable_if<std::is_base_of<A, D>::value>::type
Test (std::vector<D> const & v)
{
for ( A const & elem : v )
{
// use elem
}
}
So you have
int main ()
{
std::vector<A> a;
std::vector<B> b;
std::vector<int> c;
Test(a); // compile
Test(b); // compile
// Test(c); // compiler error
}
I have written a small piece of code where I am able to call setter and getter functions packed within a functoid using mem_fun templates.
I now would like to use this approach on top of a class hierarchy where every class might have getter and setter which can be registered as pair within a vector or array to be able to call the getter and setter if needed. GUIObject and GUICompositeObject are example classes out of the described class hierarchy.
The bound_mem_fun_t for the objects have unfortunately different types and thats the reason I don't know how to integrate them into an array/vector of pointers to the functors.
In c++11 I would use std::function. Is there a way to emulate this in c++98?
Because our compiler support only c++98 I cannot use the new features of c++11 or c++14. Also boost is not allowed.
#include <functional>
class GUIObject
{
int m_Alpha;
public:
void SetAlpha(int a) { m_Alpha = a;};
int GetAlpha() {return m_Alpha;};
};
class GUICompositeObject: public GUIObject
{
int m_NumOfChilds;
public:
void SetNumOfChilds(int NumOfChilds) { m_NumOfChilds = NumOfChilds;};
int GetNumOfChilds() {return m_NumOfChilds;};
};
template<typename T>
struct bound_mem_fun_t
{
bound_mem_fun_t(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o) :
m_GetFunc(GetFunc), m_SetFunc(SetFunc), obj(o) { } ;
int operator()() { return m_GetFunc(obj); } ;
void operator()(int i) { m_SetFunc(obj, i); } ;
std::mem_fun_t<int, T> m_GetFunc;
std::mem_fun1_t<void, T, int> m_SetFunc;
T* obj;
};
int main()
{
GUIObject kGUIObject;
GUICompositeObject kCompObj;
bound_mem_fun_t<GUIObject> GUIObjectFunc(std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject);
GUIObjectFunc(17);
int ii = GUIObjectFunc();
bound_mem_fun_t<GUICompositeObject> GUICompObjectFunc(std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj);
GUICompObjectFunc(17);
int iChilds = GUICompObjectFunc();
return 0;
}
Here is the complete solution after #filmors answer:
#include <functional>
#include <vector>
#include <iostream>
class GUIObject
{
int m_Alpha;
public:
void SetAlpha(int a) { m_Alpha = a;};
int GetAlpha() {return m_Alpha;};
};
class GUICompositeObject: public GUIObject
{
int m_NumOfChilds;
public:
void SetNumOfChilds(int NumOfChilds) { m_NumOfChilds = NumOfChilds;};
int GetNumOfChilds() {return m_NumOfChilds;};
};
struct bound_mem_fun_base
{
virtual int operator()() =0;
virtual void operator()(int) =0;
};
template<typename T>
struct bound_mem_fun_t : public bound_mem_fun_base
{
bound_mem_fun_t(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o) :
m_GetFunc(GetFunc), m_SetFunc(SetFunc), obj(o) { } ;
virtual int operator()() { return m_GetFunc(obj); } ;
virtual void operator()(int i) { m_SetFunc(obj, i); } ;
std::mem_fun_t<int, T> m_GetFunc;
std::mem_fun1_t<void, T, int> m_SetFunc;
T* obj;
};
template<typename T> bound_mem_fun_t<T>* make_setter(std::mem_fun_t<int, T> GetFunc, std::mem_fun1_t<void, T, int> SetFunc, T* o)
{
return new bound_mem_fun_t<T> (GetFunc, SetFunc, o);
}
int main()
{
GUIObject kGUIObject;
GUICompositeObject kCompObj;
std::vector<bound_mem_fun_base*> kBoundVector;
kBoundVector.push_back(new bound_mem_fun_t<GUIObject> (std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject));
kBoundVector.push_back(new bound_mem_fun_t<GUICompositeObject> (std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj));
kBoundVector.push_back(make_setter<GUIObject> (std::mem_fun(&GUIObject::GetAlpha), std::mem_fun(&GUIObject::SetAlpha), &kGUIObject));
kBoundVector.push_back(make_setter<GUICompositeObject> (std::mem_fun(&GUICompositeObject::GetNumOfChilds), std::mem_fun(&GUICompositeObject::SetNumOfChilds), &kCompObj));
for (int i = 0; i < 4 ; i++)
{
(*kBoundVector[i])(i*10);
int res = (*kBoundVector[i])();
std::cout << "Getter result " << res << "\n";
}
return 0;
}
Unfortunately the make_setter function does not really shorten the creation of the functor. Any ideas will be welcome.
Just give your bound_mem_fun_t<T> a common base class and use dynamic dispatch to solve your problem:
struct bound_mem_fun_base {
virtual int operator()() = 0;
virtual void operator()(int) = 0;
};
template <typename T>
struct bound_mem_fun_t : bound_mem_fun_t ...
Then you can keep pointers to bound_mem_fun_base in your vector and call the elements as (*v[0])().
Also, TR1 does contain std::tr1::function, is that available?
First a remark on std::function from c++11: That will not solve your problem, because you need an already bounded function pointer. This pointer must be bound to your object. I believe what you need is an own implementation to std::bind.
I started only a very! small Binder class which is hopefully a starting point for your needs. If you need to have template parameter lists in older c++ versions, take a look for loki. http://loki-lib.sourceforge.net/
As a hint I can give you a short example of what i did:
class A
{
private:
int val;
public:
A(int i): val(i) {}
void Do(int i) { std::cout << "A " << val<< " " << i << std::endl; }
};
class B
{
private:
int val;
public:
B(int i): val(i){}
void Go(int i) { std::cout << "B " << val << " " << i << std::endl; }
};
class Base
{
public:
virtual void operator()(int i)=0;
};
template <typename T>
class Binder: public Base
{
void (T::*fnct)(int);
T* obj;
public:
Binder( void(T::*_fnct)(int), T*_obj):fnct(_fnct),obj(_obj){}
void operator()(int i)
{
(obj->*fnct)(i);
}
};
int main()
{
A a(100);
B b(200);
// c++11 usage for this example
//std::function<void(int)> af= std::bind( &A::Do, &a, std::placeholders::_1);
//af(1);
// hand crafted solution
Base* actions[2];
actions[0]= new Binder<A>( &A::Do, &a);
actions[1]= new Binder<B>( &B::Go, &b);
actions[0]->operator()(55);
actions[1]->operator()(77);
}
Lets assume we have two classes
struct A
{
int x = 1;
};
struct B
{
int y = 2;
};
I want to have template that will return value of member (in a case of A I want to return value of "x", in case of B I want to return value of "y").
Example call:
const auto myVariable = f<A>();
or
A a;
const auto myVariable = f<A>(a);
I don't want to have 2 template specializations - ideally it would be one template with some kind of "if statement", but maybe it is not possible?
It may be written with C++11 (but not with C++14).
Generally how you are using templates when you have such problems - quite big template and only in one or two places you need to take values from different members - which may be deduced based of type of that variable.
PROBLEM: unnecessary it is not allowed to modify classes A and B
Why use templates at all?
int f(const A& a) { return a.x; }
int f(const B& b) { return b.y; }
Just in case you ask for the template because you want to switch between A and B at compile time...and you have a reason not to simply typedef A or B directly...
struct A
{
int x;
};
struct B
{
int y;
};
struct A1 : public A { int Get() const { return x; } };
struct B1 : public B { int Get() const { return y; } };
// Begin possible shortcut avoiding the template below:
#ifdef USE_A
typedef A1 Bar;
#endif
#ifdef USE_B
typedef B1 Bar;
#endif
// End possible shortcut.
template <class _Base>
struct CompileTimeAOrB
: public _Base
{
int Get() const
{
return _Base::Get();
}
};
#define USE_A
//#define USE_B
#ifdef USE_A
typedef CompileTimeAOrB<A1> Foo;
#endif
#ifdef USE_B
typedef CompileTimeAOrB<B1> Foo;
#endif
EDIT: Since A and B cannot be changed, introduced A1, B1 ;)
#include <iostream>
struct A
{
int value;
A() : value(2) {}
};
struct B
{
int value;
B() : value(4) {}
};
template <typename T>
int GetValue(T t)
{
return t.value;
}
int main()
{
A a;
B b;
std::cout << GetValue(a) << std::endl;
std::cout << GetValue(b) << std::endl;
return 0;
}
In order for it to work, you'd need to have the same variable or function named declared in each class you wanted this to work with.