How to pass instance of template to another instance of another template? - c++

I have two class templates that must be templates (C++). I just simplified their code to show the essence of the problem. How to pass an object (obj1) from one template (MyClass1) to another object (obj2) from second template (MyClass2)? I tried through the template parameter and the constructor, but I still have compilation errors. How to do it correctly? What is important, I don't know template parameters, therefore solution has be universal, not for specified parameters. Object should be passed by pointer or reference, I don't need its copy.
template<int a, int b>
class MyClass1 {
public:
MyClass1() {
// Do something...
}
int foo(int x) {
return a * x + b;
}
};
template<double m, double n>
class MyClass2 {
public:
MyClass2() {
// Do something
}
double bar(int x) {
// Do something with x using object of MyClass1 and then with m...
}
double zet(int x) {
// Do something with x using object of MyClass1 and then with n...
}
};
int main() {
MyClass1<4, 3> obj1;
MyClass2<3.14, 2.56> obj2; // <-- How to pass obj1 here???
// Maybe that way?: MyClass2<3.14, 2.56, obj1> obj2;
// Or that way?: MyClass2<3.14, 2.56> obj2(obj1);
obj1.foo(12);
obj2.bar(1.234);
obj2.zet(5.678);
}
I'm not sure if this is relevant to this problem, but I'm writing C++ code for AVR in Atmel Studio 7 with standard settings.

Your code does not compile with C++11 because of this:
A non-type template parameter must have a structural type, which is
one of the following types (optionally cv-qualified, the qualifiers
are ignored):
lvalue reference type (to object or to function);
an integral type;
a
pointer type (to object or to function);
a pointer to member type (to
member object or to member function);
an enumeration type;
std::nullptr_t; (since C++11)
a floating-point type; (since C++20)
Regarding your core problem, you can do the something like this:
template<int m, int n, typename Obj1Type>
class MyClass2 {
Obj1Type obj1_;
public:
MyClass2() {
// Do something
}
MyClass2(Obj1Type const& obj1) {
obj1_ = obj1;
}
// ...
};
And then in main:
int main() {
MyClass1<4, 3> obj1;
MyClass2<3, 2, MyClass1<4, 3>> obj2(obj1);
obj1.foo(12);
obj2.bar(1);
obj2.zet(5);
}
Check it out live
UPDATE
You could also make use of inheritance and create a simple base class for this purpose:
class BaseMyClass1 {};
template<int a, int b>
class MyClass1 : public BaseMyClass1 {
// ...
};
template<int m, int n>
class MyClass2 {
BaseMyClass1 obj1_;
public:
MyClass2() {
// Do something
}
template <typename Obj1Type>
MyClass2(Obj1Type const& obj1) {
obj1_ = obj1;
}
// ...
};
And then in main:
int main() {
MyClass1<4, 3> obj1;
MyClass2<3, 2> obj2(obj1);
obj1.foo(12);
obj2.bar(1);
obj2.zet(5);
}
This saves you declaring a template in template parameter list. However, this might not be the perfect solution for you because it introduces object slicing.
Check it out live

Template class accepts another template class as template parameter. So you can pass typename T for Myclass2.
Example program:
You can try something like this:
#include <iostream>
using namespace std;
template<typename T1>
class Myclass1
{
public:
Myclass1(T1 x):m1_x(x)
{
cout << "Myclass1 C'tor" << m1_x << endl;
}
T1 m1_x;
T1 get_x()
{
return m1_x;
}
};
template < typename T1 >
class Myclass2
{
public:
Myclass2(T1 x): m_x(x)
{
cout << "My class 2 C'tor with value" << m_x.get_x() << endl;
}
public:
T1 m_x;
};
int main()
{
Myclass1 <int > obj1(5000);
Myclass2< Myclass1 <int> > obj2 ( obj1 );
return 0;
}

Related

Templated Manual Destructor Call Not Working

I want to destroy the templated object, but keep the allocated memory to be filled. Unfortunately, the destructor of the object is never called, and stepping through the code, it skips the manual call.
#include <iostream>
template <typename type> class TestClass
{
private:
type *data;
public:
TestClass();
~TestClass();
template <typename T> void Set(T &&element);
void Replace();
};
template <typename type> TestClass<type>::TestClass()
{
data = reinterpret_cast<type *>(new char[sizeof(type)]);;
}
template <typename type> TestClass<type>::~TestClass()
{
}
template <typename type> template <typename T> void TestClass<type>::Set(T &&element)
{
new(data) type(static_cast<T &&>(element));
}
template <typename type> void TestClass<type>::Replace()
{
type *pointer = reinterpret_cast<type *>(&data[0]);
pointer->~type();
//Fill with data
}
class MyClass
{
public:
MyClass()
{
}
~MyClass()
{
std::cout << "Called" << "\n";
}
};
int main()
{
MyClass *myClass = new MyClass();
TestClass<MyClass *> myObject;
myObject.Set(myClass);
myObject.Replace();
return 0;
}
I have tested this in VS 2017 and on an online C++ compiler. Both skip the pointer->~type(); when stepping through and the destructor is never called.
Edit: Rewrote code which now reproduces the error.
It does call destructor.
#include <iostream>
class Type
{
public:
~Type()
{
std::cout<< __FUNCTION__ << "\n";
}
};
template <typename type> class MyClass
{
private:
type *data;
public:
MyClass();
~MyClass(){}
void Replace();
};
template <typename type> MyClass<type>::MyClass()
{
data = reinterpret_cast<type *>(new char[sizeof(type)]);;
}
template <typename type> void MyClass<type>::Replace()
{
type *pointer = &data[0];
pointer->~type();
//Fill with replacement data
}
int main()
{
MyClass<Type> myClass;
std::cout <<"Before destruction\n";
myClass.Replace();
std::cout << "After destruction\n";
return 0;
}
To allow templates to deal generally with types, C++ allows a obj.~type() or ptr->~type() syntax even when the type is not a class type (but not for an array type). The meaning is the same as whatever would happen to an automatic object of that type at the end of its scope: if it is a class type, the destructor is called, and if not, nothing happens. For the case when the type is not a class type, this syntax is called a pseudo-destructor.
Now looking at your example, you're using the class template specialization TestClass<MyClass*>. So in the instantiation of the member definition for TestClass<type>::Replace(), type is an alias for MyClass*. The statement
type *pointer = reinterpret_cast<type *>(&data[0]);
defines a variable of type type*, which is MyClass**. (The right-hand side is confusing: &data[0] is the same as data assuming it points at something, and both expressions already have type type*.)
The statement
pointer->~type();
says to destroy the object of type type which pointer points at. That is, it says to destroy the object of type MyClass* which is *pointer. MyClass* is not a class type; it is a pointer type. So this is a call to a pseudo-destructor, and absolutely nothing happens.
There's not enough context to say for certain how this would be fixed, but perhaps you need to use TestClass<MyClass> instead of TestClass<MyClass*>? (Also, in real code don't forget the Rule Of Five/Rule Of Three.)

Template pass member function with args and return value as parameter c++

I would like to pass a templated function args for class and a method of that class to call. The method has arguments as well as a return value.
Here is what I have so far. I believe I'm getting a little tripped up on the templatized function syntax:
bar.h
class Bar {
public:
Bar();
int FuncBar(int arg1);
}
foo.h
template<typename A, int (A::*Method)()>
int FuncTemplate(A* a, int bar_arg1) {
....
return a->Method(bar_arg1)
}
class Foo {
public:
explicit Foo(Bar* bar);
private:
void FuncFoo();
Bar* bar_;
}
foo.cc
Foo::Foo(Bar bar) : bar_(bar) {};
void Foo::FuncFoo() {
...
int bar_arg1 = 0;
FuncTemplate<Bar, &(*bar_)::FuncBar>(bar_, bar_arg1);
}
You need to use int (A::*Method)(int) as the function pointer type since the member function expects an int as an argument.
Also, the call to the member function needs to be (a->*Method)(bar_arg1). The syntax for calling member function using a member function is not very intuitive.
template<typename A, int (A::*Method)(int)>
int FuncTemplate(A* a, int bar_arg1) {
....
return (a->*Method)(bar_arg1)
}
Also, you need to use &Bar::FuncBar to get a pointer to the member function, not &(*bar_)::FuncBar.
void Foo::FuncFoo() {
int bar_arg1 = 0;
FuncTemplate<Bar, &Bar::FuncBar>(bar_, bar_arg1);
// ^^^^^^^^^^^^^
}

How does one use inheritance when we have a template class have template pointer

How does one use inheritance when we have a template class have template pointer
We know that base class pointer can easily point to a derived class object . I created another template class and passed base and derived in it . However even with an overloaded = operator i cant make then equal which is my need .
Please take a look at my sample code as it explains clearly the situation.
#include <iostream>
using namespace std;
class base1
{
public:
int a;
virtual int reset(){
a=0;
return a;
}
};
class derived1: public base1
{
public:
int b;
int reset(){
b=0;
return b;
}
};
template <class T>
class templateClass{
public:
T *P;
T& operator = (templateClass &b )
{
this.p = reinterpret_cast<T>(b.p);
return *this;
}
void resetMyself(){
P->reset();
}
};
int main() {
// your code goes here
templateClass<base1> *p = new templateClass<base1> () ;
templateClass<derived1> *q = new templateClass<derived1>() ;
p=q;
p->resetMyself();
return 0;
}
When i compile my code i get
prog.cpp: In function ‘int main()’:
prog.cpp:44:3: error: cannot convert ‘templateClass<derived1>*’ to ‘templateClass<base1>*’ in assignment
p=q;
^
templateClass<derived1> and templateClass<base1> are as different as int and double. You can't assign a pointer to one to a pointer to the other.
You can, however, make templateClass<derived1> assignable to templateClass<base1> with a custom templated assignment operator:
template <class T>
class templateClass{
public:
T *P;
template <class U>
templateClass& operator = (const templateClass<U> &b )
{
P = b.P;
return *this;
}
void resetMyself(){
P->reset();
}
};
Then you can do something like (demo):
templateClass<base1> p;
templateClass<derived1> q;
p = q;
Note that your original assignment operator's signature is incorrect. Also, reinterpret_cast is a terrible idea for this. To perform a pointer-to-base to pointer-to-derived conversion, use static_cast. The above version uses no cast and so allows implicit conversions only (i.e., from derived to base but not the other way around).

C++ template: retain non-type value info without store in the constructor

Suppose I have following template class:
template<unsigned char I, unsigned char F>
class FOO
{
....
}
In the main function, I have many such variables, with different (I, F), like following,
int main()
{
.....
FOO<4, 2> a;
FOO<6, 3> b;
......
}
I want to retain the value of I or F for the defined variables in my main function. Of course, I can define a public/private members for FOO and save the value of (I, F) inside the FOO's constructor, like
template<I,F>
FOO<I,F>::FOO(){
i = I;
f = F;
}
Disadvantage of this method is obvious: It enlarge the size of the FOO. IMO, (I, F) of any variable can be determined at compiling time, so there should be a way to do this without creating local variable.
The usual way (like std::array in C++11) is to do the following:
constexpr unsigned char i() const { return I; }
constexpr unsigned char f() const { return F; }
If your compiler doesn't support constexpr, remove it.
Within your class definition, you can simply refer to the parameters literally (just like any other template parameters!).
But suppose you have this:
typedef Foo<10, 20> MyFoo;
MyFoo x; // what is I, what is K?
The customary thing is to reflect the template parameters inside the class definition:
template <int A, typename T> struct Foo
{
static int const a_value = A;
typedef T type;
// ...
};
Now you can say: MyFoo::type x; return MyFoo::a_value; etc. Note that integral static class constants don't usually need a definition unless you do something like take their address, so in most cases this won't have any cost in the compiled code -- the compiler simply substitutes the value whenever it sees the name of the constant.
you can simply use the template parameters, like this:
#include <iostream>
using namespace std;
template<unsigned char I, unsigned char F>
class FOO
{
public:
void bar() {
cout << "I is: "<<I<<endl;
}
char getI() {
return I;
}
};
using namespace std;
int main(){
FOO<4,2> a;
a.bar();
cout << "getI:"<<a.getI()<<endl;
}
you don't need a copy, as in your example (i = I)
BTW: fully capitalized names like FOO are usually by convention reserved for preprocessor Macros.

C++: constructor initializer for arrays

I'm having a brain cramp... how do I initialize an array of objects properly in C++?
non-array example:
struct Foo { Foo(int x) { /* ... */ } };
struct Bar {
Foo foo;
Bar() : foo(4) {}
};
array example:
struct Foo { Foo(int x) { /* ... */ } };
struct Baz {
Foo foo[3];
// ??? I know the following syntax is wrong, but what's correct?
Baz() : foo[0](4), foo[1](5), foo[2](6) {}
};
edit: Wild & crazy workaround ideas are appreciated, but they won't help me in my case. I'm working on an embedded processor where std::vector and other STL constructs are not available, and the obvious workaround is to make a default constructor and have an explicit init() method that can be called after construction-time, so that I don't have to use initializers at all. (This is one of those cases where I've gotten spoiled by Java's final keyword + flexibility with constructors.)
Edit: see Barry's answer for something more recent, there was no way when I answered but nowadays you are rarely limited to C++98.
There is no way. You need a default constructor for array members and it will be called, afterwards, you can do any initialization you want in the constructor.
Just to update this question for C++11, this is now both possible to do and very natural:
struct Foo { Foo(int x) { /* ... */ } };
struct Baz {
Foo foo[3];
Baz() : foo{{4}, {5}, {6}} { }
};
Those braces can also be elided for an even more concise:
struct Baz {
Foo foo[3];
Baz() : foo{4, 5, 6} { }
};
Which can easily be extended to multi-dimensional arrays too:
struct Baz {
Foo foo[3][2];
Baz() : foo{1, 2, 3, 4, 5, 6} { }
};
Right now, you can't use the initializer list for array members. You're stuck doing it the hard way.
class Baz {
Foo foo[3];
Baz() {
foo[0] = Foo(4);
foo[1] = Foo(5);
foo[2] = Foo(6);
}
};
In C++0x you can write:
class Baz {
Foo foo[3];
Baz() : foo({4, 5, 6}) {}
};
Unfortunately there is no way to initialize array members till C++0x.
You could use a std::vector and push_back the Foo instances in the constructor body.
You could give Foo a default constructor (might be private and making Baz a friend).
You could use an array object that is copyable (boost or std::tr1) and initialize from a static array:
#include <boost/array.hpp>
struct Baz {
boost::array<Foo, 3> foo;
static boost::array<Foo, 3> initFoo;
Baz() : foo(initFoo)
{
}
};
boost::array<Foo, 3> Baz::initFoo = { 4, 5, 6 };
You can use C++0x auto keyword together with template specialization on for example a function named boost::make_array() (similar to make_pair()). For the case of where N is either 1 or 2 arguments we can then write variant A as
namespace boost
{
/*! Construct Array from #p a. */
template <typename T>
boost::array<T,1> make_array(const T & a)
{
return boost::array<T,2> ({{ a }});
}
/*! Construct Array from #p a, #p b. */
template <typename T>
boost::array<T,2> make_array(const T & a, const T & b)
{
return boost::array<T,2> ({{ a, b }});
}
}
and variant B as
namespace boost {
/*! Construct Array from #p a. */
template <typename T>
boost::array<T,1> make_array(const T & a)
{
boost::array<T,1> x;
x[0] = a;
return x;
}
/*! Construct Array from #p a, #p b. */
template <typename T>
boost::array<T,2> make_array(const T & a, const T & b)
{
boost::array<T,2> x;
x[0] = a;
x[1] = b;
return x;
}
}
GCC-4.6 with -std=gnu++0x and -O3 generates the exact same binary code for
auto x = boost::make_array(1,2);
using both A and B as it does for
boost::array<int, 2> x = {{1,2}};
For user defined types (UDT), though, variant B results in an extra copy constructor, which usually slow things down, and should therefore be avoided.
Note that boost::make_array errors when calling it with explicit char array literals as in the following case
auto x = boost::make_array("a","b");
I believe this is a good thing as const char* literals can be deceptive in their use.
Variadic templates, available in GCC since 4.5, can further be used reduce all template specialization boiler-plate code for each N into a single template definition of boost::make_array() defined as
/*! Construct Array from #p a, #p b. */
template <typename T, typename ... R>
boost::array<T,1+sizeof...(R)> make_array(T a, const R & ... b)
{
return boost::array<T,1+sizeof...(R)>({{ a, b... }});
}
This works pretty much as we expect. The first argument determines boost::array template argument T and all other arguments gets converted into T. For some cases this may undesirable, but I'm not sure how if this is possible to specify using variadic templates.
Perhaps boost::make_array() should go into the Boost Libraries?
This seems to work, but I'm not convinced it's right:
#include <iostream>
struct Foo { int x; Foo(int x): x(x) { } };
struct Baz {
Foo foo[3];
static int bar[3];
// Hmm...
Baz() : foo(bar) {}
};
int Baz::bar[3] = {4, 5, 6};
int main() {
Baz z;
std::cout << z.foo[1].x << "\n";
}
Output:
$ make arrayinit -B CXXFLAGS=-pedantic && ./arrayinit
g++ -pedantic arrayinit.cpp -o arrayinit
5
Caveat emptor.
Edit: nope, Comeau rejects it.
Another edit: This is kind of cheating, it just pushes the member-by-member array initialization to a different place. So it still requires Foo to have a default constructor, but if you don't have std::vector then you can implement for yourself the absolute bare minimum you need:
#include <iostream>
struct Foo {
int x;
Foo(int x): x(x) { };
Foo(){}
};
// very stripped-down replacement for vector
struct Three {
Foo data[3];
Three(int d0, int d1, int d2) {
data[0] = d0;
data[1] = d1;
data[2] = d2;
}
Foo &operator[](int idx) { return data[idx]; }
const Foo &operator[](int idx) const { return data[idx]; }
};
struct Baz {
Three foo;
static Three bar;
// construct foo using the copy ctor of Three with bar as parameter.
Baz() : foo(bar) {}
// or get rid of "bar" entirely and do this
Baz(bool) : foo(4,5,6) {}
};
Three Baz::bar(4,5,6);
int main() {
Baz z;
std::cout << z.foo[1].x << "\n";
}
z.foo isn't actually an array, but it looks about as much like one as a vector does. Adding begin() and end() functions to Three is trivial.
Only the default constructor can be called when creating objects in an array.
In the specific case when the array is a data member of the class you can't initialize it in the current version of the language. There's no syntax for that. Either provide a default constructor for array elements or use std::vector.
A standalone array can be initialized with aggregate initializer
Foo foo[3] = { 4, 5, 6 };
but unfortunately there's no corresponding syntax for the constructor initializer list.
There is no array-construction syntax that ca be used in this context, at least not directly. You can accomplish what you're trying to accomplish by something along the lines of:
Bar::Bar()
{
static const int inits [] = {4,5,6};
static const size_t numInits = sizeof(inits)/sizeof(inits[0]);
std::copy(&inits[0],&inits[numInits],foo); // be careful that there are enough slots in foo
}
...but you'll need to give Foo a default constructor.
Ideas from a twisted mind :
class mytwistedclass{
static std::vector<int> initVector;
mytwistedclass()
{
//initialise with initVector[0] and then delete it :-)
}
};
now set this initVector to something u want to before u instantiate an object. Then your objects are initialized with your parameters.
You can do it, but it's not pretty:
#include <iostream>
class A {
int mvalue;
public:
A(int value) : mvalue(value) {}
int value() { return mvalue; }
};
class B {
// TODO: hack that respects alignment of A.. maybe C++14's alignof?
char _hack[sizeof(A[3])];
A* marr;
public:
B() : marr(reinterpret_cast<A*>(_hack)) {
new (&marr[0]) A(5);
new (&marr[1]) A(6);
new (&marr[2]) A(7);
}
A* arr() { return marr; }
};
int main(int argc, char** argv) {
B b;
A* arr = b.arr();
std::cout << arr[0].value() << " " << arr[1].value() << " " << arr[2].value() << "\n";
return 0;
}
If you put this in your code, I hope you have a VERY good reason.
This is my solution for your reference:
struct Foo
{
Foo(){}//used to make compiler happy!
Foo(int x){/*...*/}
};
struct Bar
{
Foo foo[3];
Bar()
{
//initialize foo array here:
for(int i=0;i<3;++i)
{
foo[i]=Foo(4+i);
}
}
};
in visual studio 2012 or above, you can do like this
struct Foo { Foo(int x) { /* ... */ } };
struct Baz {
Foo foo[3];
Baz() : foo() { }
};
class C
{
static const int myARRAY[10]; // only declaration !!!
public:
C(){}
}
const int C::myARRAY[10]={0,1,2,3,4,5,6,7,8,9}; // here is definition
int main(void)
{
C myObj;
}