Pointers to methods & templates problem, C++ - c++

There are 2 template classes A and B having 2 private members a1, a2 and b1, b2.
template <typename T>
class A
{
private:
T a1, a2;
public:
T getA1 () const {return a1;}
T getA2 () const {return a2;}
};
template <typename T>
class B
{
private:
T b1, b2;
public:
T getB1 () const {return b1;}
T getB2 () const {return b2;}
};
In the class Test there is a need for 2 pointers pointing to getters.
class Test
{
private:
template <typename T>
static T ( *getFirst ) ();
template <typename T>
static T ( *getSecond ) ();
}
template <typename T>
T ( * Test::getFirst ) () = &A<T>::getA1; //Pointer to getA1, error
template <typename T>
T ( * Test::getSecond ) () = &B<T>::getB2; //Pointer to getB2, error
int main
{
A <double> a;
B <double> b;
double c = a.getFirst + b.getSecond;
}
T represents fundamental data types... Is it possible implement this code without specialization (i.e. pointers to class template members) or those "pointers" should be specialized? Thanks for any examples...

You're doing illegal things. See this,
template <typename T>
static T ( *getFirst ) ();
Here you're trying to define template function pointer which is illegal in C++.
The C++ Standard says in $14/1,
A template defines a family of classes
or functions.
Please note that it does not say "a template defines a family of classes, functions or function pointers". So what you're trying to do is, defining "a family of function pointers" using template, which isn't allowed.
If you want function pointer you can do something like this,
template <class T>
struct A
{
static T (*FunctionPointer)(); //function pointer
};
struct B
{
template <class T>
static T Function(); //static function, not function pointer
};
int (*A<double>::FunctionPointer)() = &B::Function<double>;
Yet better alternative is : use function object. :-)

In short, it's not possible.
First, you cannot declare a pointer to template function, only pointer to a concrete function.
Second, you tried to declare pointer to free function but A::getA1 is a member function with implicit this argument, so semantic doesn't match.
You can do something like this:
template <typename T>
struct A
{
static T get() { return T() };
};
template <typename T>
struct Holder
{
typedef T(A<T>::*F_ptr)();
static F_ptr f_ptr;
};
template <typename T>
typename Holder<T>::F_ptr Holder<T>::f_ptr = &A<T>::get;
to keep pointer to template function as a member of template class

The line:
template <typename T>
T (*Test::getFirst)() = &A<T>::getA1; //Pointer to getA1, error
Has two problems: One is that &A<T>::getA1 is of type T (A::*)()const but getFirst is of type T (*)(). These are not compatible because the former is a pointer to a member function, while the latter is not.
The second problem with the line is that the objects created would differ only in their return type. Just like you cannot manually declare both double (A::*getFirst)()const and char (A::*getFirst)()const, you also cannot create a template that would automatically declare both of them.
The line:
double c = a.getFirst + b.getSecond;
Has its own set of problems that may or may not relate to the issue at hand.
Sorry for this "non answer." maybe if you talked more about what you are trying to accomplish, rather than how you are trying to accomplish it, we will be able to help.

Your code seems quite confused, so I'm not sure I really understood what you are asking for... here is an adaptation of your example that compiles.
// This is one template class A with two getters
template <typename T>
class A
{
private:
T a1, a2;
public:
T getA1 () const {return a1;}
T getA2 () const {return a2;}
};
// This is another unrelated template class, with two other getters
template <typename T>
class B
{
private:
T b1, b2;
public:
T getB1 () const {return b1;}
T getB2 () const {return b2;}
};
// These are declarations of generic "getFirst" and "getSecond"
template<typename T1, typename T2>
T1 getFirst(const T2& t);
template<class T1, class T2>
T1 getSecond(const T2& t);
// Here I'm specializing getFirst/getSecond for the A template
template<class X>
double getFirst(const A<X>& a) { return a.getA1(); }
template<class X>
double getSecond(const A<X>& a) { return a.getA2(); }
// Here I'm doing the same for the B template
template<class X>
double getFirst(const B<X>& b) { return b.getB1(); }
template<class X>
double getSecond(const B<X>& b) { return b.getB2(); }
// Now I can use getFirst/getSecond with either A or B
int main(int argc, const char *argv[])
{
A<double> a;
B<double> b;
double c = getFirst(a) + getSecond(b);
return 0;
}

Related

How to pass structure with template variable as an argument inside member function of class in c++?

I would like to pass 'structure with template variable' as an argument inside member function of class. I am getting error "no matching function for call to". Can anyone help me? I am doing some mistake either in declaration / definition / while passing argument from the main.
template <typename T>
struct msg_1{
int var_1;
int var_2;
T *var_3;
};
template<typename T>
struct msg_2{
int var_1;
int var_2;
T *var_3;
};
class A
{
public:
int a;
int b;
template <typename T>
void test(T *, T *);
};
template <typename T>
void A::test(T *t1, T *t2)
{ cout<<"Inside test #todo Do something"; }
int main()
{
A ob;
ob.a=10;
ob.b=20;
msg_1<int> *ob_1 = new msg_1<int>;
msg_2<int> *ob_2 = new msg_2<int>;
ob.test(ob_1,ob_2);
return 0;
}
========
I have accepted the given suggestion and modified the code, but getting some error while implementing. Kindly have a look.
I have passed the structure as a parameter in test method like below
template <typename T>
struct msg1{
…
};
template<typename U>
struct msg2{
…
};
struct msg3
{
uint16_t var_4;
};
class A
{
public:
int a;
int b;
template <typename T, typename U>
void test(msg1<T> *t1, msg2<U> *t2);
};
template <typename T, typename U>
void A::test(msg1<T> *t1, msg2<U> *t2)
{
cout<<"Inside test #todo Do something";
}
int main()
{
A ob;
ob.a=10;
ob.b=20;
msg_1<msg3> *ob_1 = new msg_1<msg3>;
msg_2<msg3> *ob_2 = new msg_2<msg3>;
ob.test(ob_1,ob_2);
return 0;
}
When I am running above code in online compiler then it’s running fine but when I am implementing it in actual code to do testing then I am getting compile time error
“undefined reference to ‘void A::test< msg3, msg3 > ( msg1 *, msg2 * )’.
Can anyone please tell me what possibly I am doing wrong.
Your template function A::test is only templated with one type T and requires that both parameters have the same type T*. In your example you pass different parameters: msg_1<int> * and msg_2<int> *.
If you really want test to only accept two parameters with identical type, then you can't pass ob_1 and ob_2. If you want test to accept two parameters of different type, then you can change your class A and function A::test as follows.
class A
{
public:
int a;
int b;
template <typename T1, typename T2>
void test(T1 *, T2 *);
};
template <typename T1, typename T2>
void A::test(T1 *t1, T2 *t2)
{ cout<<"Inside test #todo Do something"; }

Template specific methods

If I have a class A
template <typename T>
class A { public: void print() const; };
I can write specific version of my methode print for specific template values my doing
template<> void A<bool>::print() const { printf("A w/ type bool\n"); }
template<> void A<int>::print() const { printf("A w/ type int\n"); }
and the calling the method print will just call the code of the good implementation (of the compiler tell me if I don't have an implementation for a specific template.
Now, if I have multiples types in my class B's template
template <typename T1, typename T2>
class B { public: void print() const; };
and if I try to do the same as before, let's say for T2
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
I get an compiler error :
error: invalid use of incomplete type 'class B<T1,bool>'
error: declaration of 'class B<T1, bool>'
What am I doing wrong ?
EDIT
My real life B class contains other methods with I do not want to specify (they work in the general case)
Having a partially specified class decalred makes that those generic methods aren't natively availlable
You can't partial specialize a function/method.
But you can partial specialize the whole class:
template <typename T1, typename T2> class B;
template<typename T1> class B<T1, bool>
{
public:
void print() const { printf("B w/ type bool\n"); }
};
What am I doing wrong?
template<> void A<bool>::print() const { printf("A w/ type bool\n"); }
template<> void A<int>::print() const { printf("A w/ type int\n"); }
These member functions are like normal functions, they are not templates with un-substituted parameters, so you are just providing definitions for the symbols, which will be used when those functions get called. (And like normal functions, if those definitions are in a header and you don't declare them inline you will get multiple definitions errors for them.)
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
This is not the same, this is providing a definition for a member function of a class template partial specialization. i.e. it's a template that will be used to generate code for the member of that partial specialization, but you haven't declared any such partial specialization, so you can't define its members.
You can make it compile by defining the partial specialization first:
// primary template
template <typename T1, typename T2>
class B { public: void print() const; };
// partial specialization
template<typename T1>
class B<T1,bool> { public: void print() const; };
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
However it is often inconvenient to have to repeat the entire class template definition just to define a partial specialization for one or two members, so it might be worth taking one of the alternative designs shown in other answers.
With templates it's best to decompose each part of the specialisation into its own template function or traits class.
Here's a clean way to do what you want:
template<typename T>
const char* type_name()
{
return "unknown";
};
template<>
const char* type_name<int>()
{
return "int";
}
template<>
const char* type_name<bool>()
{
return "bool";
}
struct foo {};
template<>
const char* type_name<foo>()
{
return "my custom foo";
}
struct bar {};
template <typename T>
class A {
public:
void print() const {
cout << "A w/ type " << type_name<T>() << '\n';
}
};
int main() {
A<bool> ab;
A<int> ai;
A<foo> af;
A<bar> abar;
ab.print();
ai.print();
af.print();
abar.print();
return 0;
}
output:
A w/ type bool
A w/ type int
A w/ type my custom foo
A w/ type unknown
Program ended with exit code: 0
With tag dispatching, you might do:
#include <iostream>
template<typename A, typename B>
class X
{
private:
template <typename U> struct Tag {};
template <typename U>
void print(Tag<U>) const;
void print(Tag<bool>) const { std::cout << "bool\n"; }
void print(Tag<int>) const{ std::cout << "int\n"; }
public:
void print() const { print(Tag<B>()); }
};
int main()
{
X<void, bool>().print();
X<void, int>().print();
}

"dual inheritance" pointer

So an A* pointer can point to any object having a base A, and a B* pointer can point to any object with a base B*. Is there anyway to make a pointer that can only point to objects that have both A and B as a base?
I'd also want it to be something I can store as a class member (perhaps a smart version) without making that class a template class.
Edit:
#KerrekSB asked below what the point of this is. Basically I want to make a number of pure virtual base classes (i.e. interfaces) say printable, flyable, something_else_able etc.
And then I might have a new class which requires in it's constructor requires something which is both printable and flyable. If it was just one or the other, you could store it as a (smart) pointer and let polymorphism take care of the rest, but I'm trying to work out how to do this if the class uses both bases.
Sure, you can use a type trait:
#include <type_traits>
template <typename T, typename A, typename B> struct has_two_bases
: std::integral_constant<bool, std::is_base_of<A, T>:: value &&
std::is_base_of<B, T>:: value> { }
Usage:
static_assert(has_two_bases<T, A, B>::value, "Not a good type");
T * p;
Does something like this fit the bill?
class W {};
class X {};
class Y {};
class Z : public X, public Y {};
template <typename A, typename B>
class DualPointer {
public:
template <typename T>
DualPointer(T *t) : a_ptr_(t), b_ptr_(t) {}
operator A*() { return a_ptr_; }
operator B*() { return b_ptr_; }
private:
A *a_ptr_;
B *b_ptr_;
};
int main() {
Z z;
DualPointer<X, Y> p(&z);
X *x = p;
Y *y = p;
return 0;
}
Or if you're in a C++11 mood:
template <typename... Ts>
class MultiPointer;
template <typename T, typename... Rest>
class MultiPointer<T, Rest...> : public MultiPointer<Rest...> {
public:
template <typename U>
MultiPointer(U *u) : MultiPointer<Rest...>(u), ptr_(u) {};
operator T*() { return ptr_; }
private:
T *ptr_;
};
template <>
class MultiPointer<> {
public:
MultiPointer(void *) {}
};
int main() {
Z z;
MultiPointer<X, Y> p(&z);
X *x = p;
Y *y = p;
return 0;
}
If you're worried about the double storage of pointers, this approach doesn't work. See comments below this answer as to why incorporating Paweł's suggestion of using a union, which works if and only if all the pointers are numerically identical (that is, there's no multiple inheritance or other shenanigans using adjusted this pointers going on), is unsafe and basically useless.
// DON'T USE THIS VARIANT!!!!
template <typename... Ts>
class MultiPointer {
public:
MultiPointer(void *) {}
};
template <typename T, typename... Rest>
class MultiPointer<T, Rest...> {
public:
template <typename U> MultiPointer(U *u) : rest_(u) { ptr_ = u; };
template <typename U> operator U*() const { return rest_; }
operator T*() const { return ptr_; }
private:
union {
T *ptr_;
MultiPointer<Rest...> rest_;
};
};
While you could write a pointer wrapper class (similar to "smart pointers", but not so smart in this case) which only accepts pointers to types derived from A and B, dereferencing them becomes ambiguous. This is a conceptual problem you can't solve with any method.
But you could provide two functions toA() and toB() and/or conversion operators in order to retrieve a pointer to one of the base classes. But as said, you can't (nicely) overload operator* to retrieve the base reference depending on the context (depending on whether an A* or a B* is needed in the context). Same with operator->.
template<typename A, typename B>
class DualPointer {
A *a; // We need two separate pointers because their distance is not known
B *b;
public:
template<typename T>
DualPointer(T* object) :
a(object),
b(object)
{ }
A *toA() const { return a; }
B *toB() const { return b; }
operator A* () const { return a; }
operator B* () const { return b; }
};
Using SFINAE you can also allow a function template which has the actual type as the template parameter, like to<MyBaseA>():
template<typename T>
typename std::enable_if<std::is_same<A, T>::value, T*>::type
to() {
return a;
}
template<typename T>
typename std::enable_if<std::is_same<B, T>::value, T*>::type
to() {
return b;
}
Demonstration of this wrapper class
You can then add such a pointer as a class member as requested in your question:
class MyClass {
DualPointer<MyBaseA, MyBaseB> pointer;
};
and access the pointer like:
pointer.toA()->memberFunctionOfA();
If your types A and B are fixed, then either drop the "template" line and replace A and B accordingly, or add a typedef DualPointer<MyBaseA, MyBaseB> MyAOrB;
Expanding on this, you could say one of the two base classes, say the first, is your "main" base class. That could then be the one the pointer acts like, so the one returned by operator* and operator->. The two operators would then look like:
A * operator-> () const { return a; }
A & operator* () const { return *a; }
Then the call from above can become as easy as
pointer->memberFunctionOfA();
but not simultaneously
pointer->memberFunctionOfB();

Designing template class with generic private member

I suppose some other folks ran into this design issue before so I hope someone could give me some advice on what to do: I have a class that is supposed to hold a private generic object. As far as I can tell, I can't get away without making the entire class a template. FINE. But now, is there any way to infer the type of the underlying object during construction from the constructor parameter, without explicitly specifying it (I want to omit the template parameter, Derived, when I instantiate the Test class):
#include <iostream>
template <typename T>
class Generic
{
};
class Derived : public Generic<int>
{
public:
Derived ();
int GetFoo ();
private:
int m_foo;
};
template <typename T>
class Test
{
public:
Test (T &underlying);
private:
T m_underlying;
};
Derived::Derived ()
{
this->m_foo = 666;
}
int Derived::GetFoo ()
{
return this->m_foo;
}
template<typename T>
Test<T>::Test (T &underlying) : m_underlying(underlying)
{
std::cout << this->m_underlying.GetFoo() << std::endl;
}
int main ()
{
Derived underlying;
Test<Derived> test(underlying);
return 0;
}
Is there any other design strategy that I should be aware of, in order to achieve my goal?
Usually you have a class template together with a type-deducing function template:
template <typename T>
struct Foo
{
Foo(T const &);
};
template <typename T>
Foo<T> make_foo(T const & t)
{
return Foo<T>(t);
}
Usage:
auto foo = make_foo(1728); // makes a Foo<int>
This idea is used countless times in the standard library (such as make_pair, make_tuple, make_shared). The guiding principle is that you should say the desired typename at most one time, and not at all if it can be inferred.
Just make a function to create Test object:
template <typename T>
Test<T> make_test(T& underlying)
{
return Test<T>(underlying);
}
int main ()
{
Derived underlying;
auto test = make_test(underlying);
return 0;
}

C++ Compile-time polymorphism

There two unrelated structures A and B
template <typename T>
struct A {};
template <typename T>
struct B {};
one enum type
typedef enum { ma, mb} M;
and class C containing function templates
class C
{
public:
template <typename T>
static void f1 ( A <T> &a) {}
template <typename T>
static void f2 ( B <T> &b) {}
template <typename U>
static void algo (U &u, M m)
{
/*Long algorithm here
....
*/
if ( m == ma) f1(u);
else f2(u);
}
};
Static method algo contains some algorithm, that is quite difficult... It modified some values and results into structure A or B.
I would like to run static method algo with objects A or B depending on M value. But how to say it to my compiler :-)
int main()
{
A <double> a;
C::algo (a, ma); //Error
}
Error 1 error C2784: 'void C::f1(A<T>)' : could not deduce template argument for 'A<T>' from 'B<T>
A] I was thinking about pointer to function, but they are not usable with function templates.
B] Maybe a compile polymorphism could help
template <typename U, M m>
static void algo (U &u, M <m> ) { ...} //Common for ma
template <typename U, M m>
static void algo (U &u, M <mb> ) { ...} //Spec. for mb
But this solution has one big problem: Both implementations should unnecessarily include almost the same code (why to write the algorithm twice?).
So I need one function algo() processing both types of arguments A and B. Is there any more comfortable solution?
It seems that you are using the enum to convey type information from the user. I would suggest that you don't.
In the simplest case if f1 and f2 are renamed f, then you can remove the if altogether and just call it. The compiler will call the appropriate overload for you.
If you cannot or don't want to rename the function templates, then you can write a helper template that will dispatch for you (basic class template undefined, specialisations for A and B that dispatch to the appropriate static function)
If the enum is used for something else (that the compiler cannot resolve for you), you can still pass it around and rewrite the helper to dispatch on the enum rather than the type of the argument and you will have to rewrite the code to have the enum value as a compile time constant (simplest: pass it as template argument to algo). In this case ou can write function specialisations instead of classes if you want, as they would be full specialisations. But note that if you can avoid having to pass it you will remove a whole family of errors: passing the wrong enum value.
// Remove the enum and rename the functions to be overloads:
//
struct C { // If everything is static, you might want to consider using a
// namespace rather than a class to bind the functions together...
// it will make life easier
template <typename T>
static void f( A<T> & ) { /* implement A version */ }
template <typename T>
static void f( B<T> & ) { /* implement B version */ }
template <typename T> // This T is either A<U> or B<U> for a given type U
static void algo( T & arg ) {
// common code
f( arg ); // compiler will pick up the appropriate template from above
}
};
For the other alternatives, it is easier if the enclosing scope is a namespace, but the idea would be the same (just might need to fight the syntax a bit harder:
template <typename T>
struct dispatcher;
template <typename T>
struct dispatcher< A<T> > {
static void f( A<T>& arg ) {
C::f1( arg );
}
};
template <typename T>
struct dispatcher< B<T> > {
static void f( B<T>& arg ) {
C::f2( arg );
}
};
template <typename T>
void C::algo( T & arg ) {
// common code
dispatcher<T>::f( arg );
}
Again, getting this to work with a class might be a bit trickier as it will probably need a couple of forward declarations, and I don't have a compiler at hand, but the sketch should lead you in the right direction.
Normal function overloading is sufficient:
template <typename T>
static void f1 ( A <T> &a) {}
template <typename T>
static void f2 ( B <T> &b) {}
template <typename T>
static void algo (A<T>& u) {
f1(u);
}
template <typename T>
static void algo (B<T>& u) {
f2(u);
}
And then:
A<int> a;
Foo::algo(a);
Although it's not clear what you stand to gain from such an arrangement.
If you realy need to do that in one function, you can use typetraits:
template<typename T, T Val>
struct value_type { static const T Value = Val; };
struct true_type : public value_type<bool, true>{};
struct false_type : public value_type<bool, false>{};
template<class T>
struct isClassA : public false_type{};
template<>
struct isClassA<A> : public true_type{};
template < typename T >
void Algo( T& rcT )
{
if ( true == isClassA<T>::Value )
{
// Class A algorithm
}
else
{
// Other algorithm
}
};
the value of m parameter is unknown until runtime, so the compiler has to generate code for both if (m == ma) and else branches when it specialize the function.
It then complains since it can't understand what he should do if you happen to call C::algo(a,mb) or similar.
As Jon suggested, overloading should fix your case, try using this code:
template<typename U>
static void f12(A<U>&u) { f1(u); }
template<typename U>
static void f12(B<U>&u) { f2(u); }
template<typename U>
static void algo(U& u, M m)
{
/* long algorithm here
...
*/
//use overloading to switch over U type instead of M value
f12(u);
}
Also you can use function pointers with template functions, as long as you specify the template parameters:
template<typename U>
static void algo(U& u, M m, void(*)(U&) func)
{
/* ... */
(*func)(u);
}
int main()
{
A <double> a;
C::algo (a, ma, &C::f1<double> );
}