Passing a template class as an argument to a function - c++

If I define a class using a template such as
template<class K, class V>
class myclass {
...
};
is there a way to pass objects defined by myclass to functions without using a template for the function? In order words, for every function that accepts myclass objects, does it also need to be defined using template< class K, class V> ?
The main reason for this is that I would like define a set of static functions that act on myclass objects so that I may limit the scope of these functions within their cpp files and not in header files.

Make your template class inherit from some base class:
template<class K, class V>
class myclass : mybaseclass { ... };
where the base class declares the public functionality of the template as pure virtual. This way you only have one function rather than one function for each K, V combination.

No, you cannot. A class template is not a class -- it is only a template. Only once you plug in the template parameters do you get a type, and for each different set of parameters you get a different, unrelated type.
Perhaps it's feasible for you to run some sort of type-erasing scheme, whereby you have a single container class which contains an abstract member pointer, and for each type you instantiate a concrete derived object. (Check out Boost.any.)
A bit like this:
class MyClassHolder { };
template <typename K, typename V>
class MyClassConcrete { };
class MyClass
{
MyClassHolder * p;
public:
template <typename K, typename V> init(...) // could be a constructor
{
p = new MyClassConcrete<K, V>();
}
};
Now you can make your function accept a MyClass, but you have to add enough virtual functions to MyClassHolder, implement them in MyClassConcrete and expose them in MyClass that you can realise all your desired semantics.

Yes, if you want your functions to be able to accept any instantiation of your template class they too must be template (typically with the same template parameters that are used for the class).
On the other hand, you can have your template class inherit from a non-template class that still allows you to operate the derived class via virtual functions. Also, to hide the type of your class and avoid riddling all your code of templates, there are the several techniques of type erasure.

No, you will have to make the functions templated as well (unless of course they will be limited to only working with a specific specialization of myclass).

You could do this:
void myfunc(const myclass<int, int>& mc) {}
Only if you wanted to be able to pass any type to your myclass argument in your function, would you need to make that myfunc a template too.

Due to C++'s static nature, you must instantiate a copy of the function for each (K, V) pair in the source since the compiler will have to generate code to access each pair's members differently.

While your reason is not entirely clear to me, yes, each function that takes a myclass as a parameter will also have to be templated on K and V. If you manage to abstract the basics, you could have each myclass< K, V > (which is a different type for each combination of K and V) inherit from a single base class that implements the functionality, or forwards it through virtual functions.

Related

C++ - same static method for any type of a template class

I have 2 templated classes, Matrix4x4t and Vector3t, and a number of static methods in Matrix4x4t that operate on them both. Matrix4x4t is defined as follows, with one of said static methods included:
template <class T>
class Matrix4x4t
{
public:
T values[16];
...
template <class W, class U, class V>
static void multiply3x3Vector3(const Matrix4x4t<W> &m,
const Vector3t<U> &columnVector,
Vector3t<V> &result);
...
};
The idea of multiply3x3Vector3 is to take any possible type of matrix (m) and vector (columnVector), perform multiplication, then store the result in a vector (result), converting to it's type if different. This works well and allows me to do the following:
Matrix4x4t<double> matd;
Vector3t<float> vec3f(1.0f, 2.0f, 3.0f);
Vector3t<int> resulti;
Matrix4x4t<float>::multiply3x3Vector3(matd, vec3f, resulti); //This works
Matrix4x4t<double>::multiply3x3Vector3(matd, vec3f, resulti); //So does this
The issue is that if I'm understanding correctly, the compiler will create 2 separate definitions of multiple3x3Vector3, one for Matrix4x4t<int> and another for Matrix4x4t<double>, even though they take the same types and do the same thing. It's probably also unclear for the user why they need to use a specific type of Matrix4x4t for each call when they produce the same result, and it would be nicer if they could just call:
Matrix4x4t::multiply3x3Vector3(matd, vec3f, resulti);
The solution to both is to make multiple3x3Vector3 a function separate from the class itself, but I like having it inside the scope of Matrix4x4t. I could have static methods that simply call an external function, but before I go this route I thought I'd ask if there is something I'm missing that would solve the two issues and let me keep the method inside the class?
Well, here's one option to make the requested Matrix4x4t::multiply3x3Vector3(matd, vec3f, resulti) syntax work correctly:
template <class T=void>
class Matrix4x4t;
template <>
class Matrix4x4t<void>
{
public:
template <class W, class U, class V>
static void multiply3x3Vector3(const Matrix4x4t<W> &m,
const Vector3t<U> &columnVector,
Vector3t<V> &result);
...
};
template <class T>
class Matrix4x4t // perhaps inherit Matrix4x4t<void>
{
public:
T values[16];
...
};
But as 5gon12eder commented, putting these associated functions in the namespace and letting them be found via Koenig lookup is even nicer and more consistent with accepted C++ style.

Abstract class accessing the implemented type through a templated virtual function?

I was wondering if there could be any way to write a template function in an abstract class, and have it (the template function) automatically instantiated with the type of the derived class?
So you have a class that looks something like this
class A
{
virtual template < typename T>
void vtfunc(void)
};
class B : public A
{
/// No declared members pertaining to this example
}
Then, whenever a class derived from A is declared, it compiles "vtfunc" with itself as the template parameter T.
Then, calling vtfunc() through an interface of A calls the isntance of that function compiled for its derived class B.
Is there any way of doing this, or writing something fiddley that have this effect?
Obviously I am aware that the template parameter could only affect the internals of the class, and not the return type and parameters - they would need to be the same because of the way polymorphism works.
I’m not sure what you’re after but one common pattern is the so-called curiously recurring template pattern; here, the base class itself is the template, not its member functions. In other words:
template <typename T>
class A
{
virtual void vtfunc(void)
};
class B : public A<B>
{
…
};
Consider using a non-member function instead.

How to declare data members that are objects of any type in a class

In this piece I'm trying to declare in Class B a list that can hold objects of Class A of any type, such as A<int>, A<double>, A<float>. I intend to add A objects to the list during runtime:
#include <list>
template <class T> class A {};
class B {
template<class T> std::list<A<T>*> objects;
};
It seems like making a list like this should work but compiling it gives an error:
Line 6: error: data member 'objects' cannot be a member template
compilation terminated due to -Wfatal-errors.
Can somebody explain why this doesn't work and how I can fix it?
That's just not how C++ works. If you want to group different objects together, they need to have at least some relation. Being instantiations of the same class template doesn't imply that they are related, they're completely distinct types. If you want a list of A<T>*s, better make a list of base-class pointers and forward operations through virtual functions:
class A_base{
public:
virtual void foo() = 0;
virtual ~A_base() { }
};
template<class T>
class A : public A_base{
public:
void foo(){
// ...
}
};
class B{
std::list<A_base*> objects;
};
Member variables aren't allowed to be templates. Only member functions can be templates. You'll have to templatize the enclosing class B instead:
template <class T>
class B {
std::list<A<T>*> objects;
};
Unfortunately you cannot have template variables. Only option to declare a member data is to make the class template:
template<class T>
class B {
std::list<A<T>*> objects;
};
Depending on what you're doing, type erasure might be an option. On the Tension Between Object-Oriented and Generic Programming in C++ is my favorite write-up on the subject.
In a nutshell, you convert the static dispatch enabled by the templates into dynamic dispatch through a custom inheritance tree you setup on the fly. Instead of storing A<T>, you create a new type that has the common interface you desire, and using some template/inhertiance voodoo this new type stores an A<T> without actually exposing the T. So A<int> and A<double> and A<A<std::list<A<int> > > > and some_type_that_looks_like_A_but_really_isnt all reduce down to a single type.
But you have to have a common interface, independant of that parameter. If you can't, things get more difficult.
Boost.Any is a good example, as is std::shared_ptr [which uses type erasure to remember how to delete the pointer passed to it even in the face of non-polymorphic inheritance].
Make B class template just like you've made A a class template:
template<class T>
class B {
std::list<A<T>*> objects;
};

Vector template question

Question as I have not done much with vectors and templates.
If I have a class foo that is templated class and I want to create a vector of foo pointers regardless of foo type, what would the syntax look like?
There is no direct way to do this. Different instantiations of the same template are treated as distinct classes with no relation to one another.
If you want to treat them uniformly, one option is to create a base class that the template foo class then inherits from. For example:
class foo_base {
/* ... */
};
template <typename T> class foo: public foo_base {
/* ... */
};
Now, you can create a vector<foo_base*> to store pointers to foo_base objects, which are in turn all specializations of foo.
You wouldn't. Every instantiation of the class template foo (e.g. foo<int>, foo<char> etc) is a distinct type. foo itself is not a type.
You'd need some base class for them and store pointers, making use of polymorphism.
Not possible. When you use a class template anywhere, you need it instantiated on a type.
One possibility to circumvent that, is to provide a polymorphic interface base class for foo and have a vector of those pointers.
class IFoo{
virtual void bar() = 0;
virtual int baz() = 0;
};
template<class T>
class Foo : IFoo{
// concrete implementations for bar and baz
};
// somewhere in your code:
std::vector<IFoo*> vecFoo.
vecFoo.push_back(new Foo<int>);
The obvious problem with that is, that you can't need to know each possible return value for your bar and baz functions.
You cannot have a vector of foo<?>. The compiler when it creates the vector needs to know precisely what type it stores because every instantiation of foo<?> could potentially have a different size and entirely different members (because you can provide explicit and partial specializations).
You need to give the foo<T> a common base class and then put baseclass pointers into the vector (preferably using shared_ptr or something similar).
As an alternative there are ready classes that hide this from you and act like a container of references. Among them is boost::ptr_vector, which however also need a common type to store.
class common_base {
/* functions to access the non-templates parts of a foo<T> .. */
};
template<typename T> class foo : public common_base { };
If you are trying to emulate concept: "vector of pointers to Foo" without specifying T, you are trying to emulate template typedefs that are not supported by current standard.
The workaround is
template <class T>
my_vector
{
typedef std::vector<Foo<T>*> type;
}
If, instead, you can afford polymorphic interface for your Foo guy, I would do that as it was already suggested.

Inherit from specialized templated base class and call the right method

I.e. I got 2 specialized types of:
template <class Type, class Base> struct Instruction {};
to compile-time-select the appropriate type from within a type list.
like:
template <class Base> struct Instruction<Int2Type<Add_Type>, Base >
{
void add() {}
};
template <class Base> struct Instruction<Int2Type<Mul_Type>, Base > :
Instruction<Int2Type<Add_Type>, Base >
{
void mul()
{
add(); ???? <== not working (not resolved)
}
};
What's the solution for this?
Thank you
Martin
add() doesn't appear to depend on any template parameters (it's not a "dependent name"), so the compiler doesn't search for it in the templated base class.
One way to make it clear to the compiler that add() is supposed to be a member function/dependent name, is to explicitly specify this-> when you use the function:
void mul()
{
this->add();
}
this implicitly depends on the template parameters, which makes add a dependent name that is looked up in the templated base class.
See also this entry of the C++ FAQ lite, and the next/previous ones.
Got it using a "using base method" clause like:
using base::add;
One disadvantage is to declare that using clauses for all base methods. On advantage is the implicit distinctive nature of it selecting only that methods, which are allowed to resolve (use).
Sorry for that question of a dude which forgets his head somewhere.