I wish to create a class that can convert between arrays of floats and doubles polymorphically. That is, the instance concerned (parameterised by <double> or <float>) and the decision to pass a float* or double* is decided at runtime, not statically.
As a proposed answer to another question, but modified according to this answer (because I understand it's not possible to fully specialise a member function template inside a class), a pure virtual base class BaseDest that provides simple overloaded member functions is sub-classed to define DestImpl<T>. I use this base class to maintain a dynamic collection of DestImpl<T> instances, with varying T. This class provides explicit overloads of the assign() member function; one for a double *, and another for a float *. The idea is that at run-time, BaseDest::assign() is called via a polymorphic pointer or reference, and this in turn calls the correct virtual assign() member function in DestImpl<T>.
Now, it is important that then the non-pointer type of the array matches T in DestImpl<T>, that a fast_copy() function is called (perhaps a memcpy), and when the types do not match a slower statically-cast-item-by-item copy is performed. So the assign() member function offloads this to a templated functor. There are two specialisations for this functor - one where the type parameter of the functor matches the type of DestImpl<T> (and therefore invokes a fast copy), and a fall-back one that catches all other cases (and invokes a slow copy).
However, I am unable to get the following code to compile. The comments show where the compiler error and warning appear - I suspect they are related. What I don't understand is why the second specialisation of apply_helper is unable to be instantiated as apply_helper<double>.
class BaseDest {
public:
virtual ~BaseDest() {}
virtual void assign(const double * v, size_t cnt) = 0;
virtual void assign(const float * v, size_t cnt) = 0;
};
template <typename T>
class DestImpl : public BaseDest {
public:
void assign(const double * v, size_t cnt) {
assign_helper<T>()(v, cnt);
}
void assign(const float * v, size_t cnt) {
assign_helper<T>()(v, cnt); // ERROR: no matching function for call to object of type 'assign_helper<double>'
}
protected:
template <typename U>
struct assign_helper {
void operator()(const U * v, size_t cnt) {
for (size_t i = 0; i < cnt; ++i) {
//slow_copy(v[i]);
}
}
};
template <typename U>
struct assign_helper<T> { // WARNING: Class template partial specialization contains a template parameter that can not be deduced; this partial specialization will never be used
void operator()(const T * v, size_t cnt) {
//fast_copy(v, cnt);
}
};
};
void test() {
DestImpl<double> d; // error mentioned above appears when this is present
}
EDIT: here's something that does seem to work - moving the assign_helper struct (now a class) out of the DestImpl<T> class definition. I'm not sure this is the right way to do it, but it does seem to work so far:
// slow copy between different types
template <typename T, typename U>
class assign_helper {
public:
void operator()(const U *v, size_t cnt) {
// slow copy
}
};
// fast copy between same types
template <typename T>
class assign_helper<T, T> {
public:
void operator()(const T * v, size_t cnt) {
// fast copy
}
};
class BaseDest {
public:
virtual ~BaseDest() {}
virtual void assign(const double * v, size_t cnt) = 0;
virtual void assign(const float * v, size_t cnt) = 0;
};
template <typename T>
class DestImpl : public BaseDest {
public:
virtual void assign(const double * v, size_t cnt) {
assign_helper<T, double>()(v, cnt);
}
virtual void assign(const float * v, size_t cnt) {
assign_helper<T, float>()(v, cnt);
}
};
template <typename U>
struct assign_helper<T> { // WARNING: Class template partial specialization contains a template parameter that can not be deduced; this partial specialization will never be used
The above is the cause of your error. The warning explicitly tells you that this definition will never be used. What you want instead of template < typename U > is template <>.
Related
So I have a tremendous number of template specializations of this template:
template <typename T> // Same
struct foo { // Same
using type_name = T; // Same
foo(const int base) : _base(base) {} // May take other parameters
void func(const T& param) {} // This function signature will be the same but body will differ
int _base; // Same but may have more members
}; // Same
So an example specialization would be:
template<>
struct foo<float> {
using type_name = T;
foo(const int base, const int child) : _base(base), _child(child) {}
void func(const T& param) { cout << param * _child << endl; }
int _base;
int _child;
};
Obviously this is a toy example and the body of _func will be more involved. But I think this expresses the idea. I can obviously make a macro to help with the boilerplate and put the implementation of the specialized version of the function in an implementation file.
But I was hoping that C++ provided me a way to do this without macros. Is there another way for me avoid writing the boilerplate over and over?
you can have multiple specialization for the function but not for the whole class
like this
#include <iostream>
#include <string>
template<typename T>
struct foo {
//common generic code
using type_name = T;
foo(const int base, const int child) : _base(base), _child(child) {}
void func(const T& param);
int _base;
int _child;
};
template<>
void foo<float>::func(const type_name&) {
//implementation
std::cout << "float" << std::endl;
}
template<>
void foo<int>::func(const type_name&) {
//implementation
std::cout << "int" << std::endl;
}
int main() {
foo<int> tint(0, 0);
foo<float> fint(0, 0);
tint.func(0);
fint.func(0);
}
You can use some light inheritance of data structs to help you separate the differences in member layout and constructor definitions from the main template.
//Define an internal aggregate type you can specialize for your various template parameters
template <typename T>
struct foo_data {
foo(const int base) : _base(base) {}
int _base;
};
//Then derive privately from the data struct (or publicly if you really desire)
template <typename T>
struct foo : private foo_data<T> {
using type_name = T;
using foo_data<T>::foo_data<T>; //Make the base class constructors visible
void func(const T& param); //Use member specialization as suggested by the other answer
};
I will leave it to you to decide if it is better this way or not, but the upshot is that all the common parts are completely separated from all the uncommon parts.
In a comment under another answer I erroneously described this as CRTP. It isn't and it doesn't have any of the drawbacks as CRTP.
If you really need to preserve standard layout, then you can simulate inheritance manually with explicit delegation and perfect forwarding.
template <typename T>
struct foo {
using type_name = T;
template <typename... Args>
foo(Args&&... args) : base_data_(std::forward<Args>(args)...) {}
void func(const T& param); //Use member specialization as suggested by the other answer
foo_data<T> base_data_;
};
One drawback is I don't think the delegating constructor will SFINAE properly as written, and it also eats noexcept specifiers and explicit. Fixing those issues(if required) is left as an exercise to the reader.
There is no nice way to avoid some redundancy in notation when implementing specializations of templated types. There are some techniques to avoid duplication of actual code, such as
Using a traits template to provide type-specific things
template<typename T>
struct foo_traits { ... }; // provide many specialisations
template<typename T> // no specialisations
struct foo
{
using traits = foo_traits<T>;
template<typename...Aars>
explicit foo(Args&&...args)
: data(std::forward<Args>(args)...) {}
int do_something_specific(T x)
{ return traits::do_something(data,x); }
private:
typename traits::data data;
};
a very similar approach is to use a specialized base class:
template<typename T>
struct foo_base { ... }; // provide many specialisations
template<typename T> // no specialisations
struct foo : foo_base<T>
{
using base = foo_base<T>;
template<typename...Aars>
explicit foo(int m, Args&&...args)
: base(std::forward<Args>(args)...)
, more_data(m) {}
int do_something_specific(T x)
{ return base::do_something(x,more_data); }
private:
int more_data;
};
The constructor of foo is a variadic template in order to allow the base class's constructor to take any number and type of arguments.
Of you can use a common base class and specialize the derived classes. This can be done with the Curiously recurring template pattern (CRTP)
template<typename Derived>
struct foo_base // no specializations
{
using type = typename Derived::type;
int do_something(type x)
{
auto result = static_cast<Derived*>(this)->specific_method(x);
return do_some_common_stuff(result);
}
protected:
foo_base(type x) : data(x) {}
type data;
private:
int do_some_common_stuff(type x)
{ /* ... */ }
};
template<typename T> // some specialisations
struct foo : foo_base<foo<T>>
{
using base = foo_base<foo>;
using type = T;
using common_type = typename base::common_type;
using base::do_something;
explicit foo(type x, type y)
: base(x), extra_data(y) {}
protected:
type specific_method(type x)
{ /* ... */ }
private:
type extra_data;
};
Note that foo_base is already a template (unlike the situation with ordinary polymorphism), so you can do a lot of specific stuff there already. Only things that are done differently (not merely with different types) need specializations of foo.
Finally, you can combine these approaches, for example traits classes with CRTP.
All these methods implement some type of static or compile-time polymorphism, rather than real or dynamic polymorphism: there are no virtual functions and hence no virtual table and no overhead for table look-up. It is all resolved at compile time.
This is usually done through inheritance - you put the immutable part into base class, and specialize the children.
I do not think you need an example for that, but let me know if you do.
I am trying to write a Bheap in templates and the insert function involving a generic comparison function. What is the usual way to do this? I know how to use function pointer in C. But Is there any typical C++ way to do that?
Someone told the first one, which class F could represent anything any function. But I want this function to be a comparison function which like f(T,T). While the second guy say something about the functors
template <class T, class F>class Bheap
{
public:
Bheap<T>(int allocateSize);
void insert(T value, F f);
void getMax();
private:
int sizeUsed;
int allocateSize;
vector<T> myBheap;
};
You should implement your class and the insert function, assuming whatever is passed is correct in terms of the number of arguments. If the number of arguments is not 2, the compiler will let you know.
This is the desired effect in these cases. Let the compiler detect that the function is not valid, and thus the user has to change the function to the correct requirements.
A demonstration using your code would be this:
#include <vector>
template <class T, class F>
class Bheap
{
public:
Bheap(int allocateSize) {}
void insert(T value, F f)
{
f(value, value);
}
void getMax();
private:
int sizeUsed;
int allocateSize;
std::vector<T> myBheap;
};
void SomeFunction(int, int)
{}
int main()
{
typedef void (*fn)(int, int);
Bheap<int, fn> b(10);
b.insert(10, SomeFunction);
}
You will see that this compiles and links correctly (I used a function pointer, but a functor with an overloaded operator() would also suffice).
Now if the user's function is changed to one that takes 1 argument, we get a different scenario:
#include <vector>
template <class T, class F>
class Bheap
{
public:
Bheap(int allocateSize) {}
void insert(T value, F f)
{
f(value, value);
}
void getMax();
private:
int sizeUsed;
int allocateSize;
std::vector<T> myBheap;
};
void SomeFunction(int)
{}
int main()
{
typedef void (*fn)(int);
Bheap<int, fn> b(10);
b.insert(10, SomeFunction);
}
The invalid function will make your class fail to compile. Since your template requires a 2 argument function, passing a 1 argument function via pointer causes the error (which you can see here: http://ideone.com/rT7RRa)
For function objects, here is an example of successful compilation:
http://ideone.com/yvWD5o
For unsuccessful compilation:
http://ideone.com/yjeAWB
A functor is a struct providing one or more overloads of operator (), which makes it a choice if you have several comparisons:
// Having a struct X { K key, V value };
struct Less {
template <typename K, typename V>
operator bool () (const X<K, V>& a, const X<K, V>& b> const {
return a.key < b.key;
}
template <typename K, typename V>
operator bool () (const X<K, V>& a, const K& b> const {
return a.key < b;
}
template <typename K, typename V>
operator bool () (const K& a, const X<K, V>& b> const {
return a < b.key;
}
};
Consider the following code:
/* aclass.h */
class AClass
{
public:
template<size_t N, class Vector>
void aMethod(const Vector &);
};
/* aclass.inl */
// method for any N
template<size_t N, class Vector>
void AClass::aMethod(const Vector &) { ... }
// method for N = 1
template<class Vector>
void AClass::aMethod<1>(const Vector &) { ... }
/* main.cpp */
int main()
{
AClass inst;
std::vector<float> data;
// calls method for any N
inst.aMethod<20>(data);
// calls method for N = 1
inst.aMethod<1>(data);
}
I can't seem to find the correct syntax for specializing a single template argument of integer type - and not even sure if it is legal. I looked around a bit, but didn't find anyone with this problem...
These are the errors i get (from msvc):
error C2244 : 'AClass::aMethod' : unable to match function definition to an existing declaration
error C2768 : 'AClass::aMethod' : illegal use of explicit template arguments
How would i go on about solving this problem?
There ain't no such thing as a partial specialization of a function template.
To achieve your goal, you could go through a helper class, which can be partially specialized:
class AClass;
template<size_t N, class Vector>
struct AMethodHelper {
static void Do(AClass* pThis, const Vector&) {
// General for N != 1
}
};
template<class Vector>
struct AMethodHelper<1, Vector> {
static void Do(AClass* pThis, const Vector&) {
// Special for N == 1
}
};
class AClass
{
public:
template<size_t N, class Vector>
void aMethod(const Vector & v) {
AMethodHelper<N, Vector>::Do(this, v);
}
};
Or, you could use two overloads selected with SFINAE:
class AClass
{
public:
template<size_t N, class Vector>
typename enable_if<N!=1>::type aMethod(const Vector &) {
// General for N != 1
}
template<size_t N, class Vector>
typename enable_if<N==1>::type aMethod(const Vector &) {
// Special for N == 1
}
};
Or, I suppose, you could just have one method with if (N == 1) inside. I suspect any decent compiler would be smart enough to eliminate dead code in any given instantiation.
I'm trying to reduce the number of template function instantiations, but am running into a snag.
Suppose we have the following class (I know it's not optimized: this is done on purpose to illustrate the issue):
//class no_inherit is implemented the same way as class base (below).
//This is done to illustrate the issue I'm seeing.
template<typename T, size_t SIZE>
class no_inherit
{
private:
T m_data[SIZE];
const size_t m_size;
public:
no_inherit() :m_size(SIZE){}
T& operator[](size_t i)
{return m_data[i];}
inline size_t size() const
{return m_size;}
};
The following function:
template<typename T>
void huge_func(T& v)
{
//..do lots of stuff with v. For example
for(size_t i = 0; i < v.size(); ++i)
v[i] = v[i] + i;
//...do lots more with v
}
And the following code:
int main()
{
no_inherit<int, 4> v1;
no_inherit<int, 2> v2;
huge_func(v1);
huge_func(v2);
}
huge_func() would get instantiated twice:
void huge_func(no_inherit<int, 4>& v);
void huge_func(no_inherit<int, 2>& v);
Since huge_func() is, well, huge, I'm trying to reduce the instantiation count by taking one of the template parameters and turning it into a dynamic parameter by creating the following class hierarchy:
//Base class only has 1 template parameter.
template<typename T>
class base
{
private:
T *m_data;
const size_t m_size; //hold child's templated size parameter.
protected:
inline base(T* data, size_t size): m_data(data), m_size(size){}
public:
T& operator[](size_t i)
{return m_data[i];}
inline size_t size() const
{return m_size;}
};
//Child class has two template parameters
template<typename T, size_t SIZE>
class inherit: public base<T>
{
private:
T m_data[SIZE];
public:
//Pass template parameter to base class
inherit() : base<T>(m_data, SIZE){}
};
And I call huge_func() as follows:
int main()
{
inherit<int, 4> v1;
inherit<int, 2> v2;
//make sure only one instantiation of huge_func() is made
//by using the same type.
base<int> &v1b = v1;
base<int> &v2b = v2;
huge_func(v1b);
huge_func(v2b);
}
This would only instantiate a single huge_func() function:
void huge_func(base<int>& v);
And thus would decrease the code size.
But ALAS! The code size increases when I use the class hierarchy. How is this possible?
Even more bizzare, if I have the following code.
int main()
{
inherit<int, 4> v1;
inherit<int, 2> v2;
huge_func(v1);
huge_func(v2);
}
The code size is the same as calling huge_func(v1b) and huge_func(v2b).
What is the compiler doing?
First of all, if huge_func is indeed "huge", you likely would benefit from splitting it up into several reusable smaller functions.
That aside, you can also template-ize it:
template<typename T, int SIZE> void huge_func(no_inherit<T, SIZE>& v)
{
// function implementation goes here
}
Then you are implementing it once, and you maintain your flat class structure.
I have a template and I have the methods T get(int i) and set(int i, T val). I have to make traits class which change not behavior but the arguements which set and get have.
template<typename T,int Roz>
class Wektor{
public:
T tab[Roz];
T get(int i)
{
return tab[i];
}
void set(T val,int i)
{
tab[i]=val;
}
}
So the traits class have to change the get and set. If T is int or double we gets parametr by copy
int
int get(int i);
void set(int val,int i);
double
double get(int i);
void set(double val,int i);
for others types:
T* get(int i);
void set(T* val,int i);
That we must do in traits not by specialization of template.
So I write tratis like this:
template<typename T,int Roz>
class traitsWektor
{
public:
T tab[Roz];
T get(int i)
{
return tab[i];
}
void set(T val,int i)
{
tab[i]=val;
}
}
So here I stuck. I think i should make
template<typename T, int Roz>
class Wektor : public traitsWektor<T,Roz>
But i am not sure is that right and is still tratis.
You should separate the class template (Wektor) and the parameter type deduction:
template <class T>
struct WektorParamTraits {
typedef T const& type;
//or if you might have different types as getter return type and setter arg
typedef T const& getterReturn;
typedef T const& setterArg;
};
In that case, T is the "default" type for your getter/setter arguments. Specialize it for any type you need.
The class definition now should look like follows:
template<typename T,int Roz>
class Wektor{
T tab[Roz]; //make member variables private
public:
typename WektorParamTraits<T>::getterReturn get(int i) //const?
{
return tab[i];
}
void set(typename WektorParamTraits<T>::setterArg val,int i)
{
tab[i]=val;
}
};
Update: as was noted in the comments, you might need to define other implementations for get and set e.g. if your return type is a pointer. There are several different approaches to do that:
define functions in the traits to correctly convert between tab[i] and the argument/return value.
If it's only about pointers and non-pointers, provide two versions of the getters and setters and use std::enable_if with std::is_pointer and whatever else is needed to disable one of them.
Use the simple class definition you posted here and specialize it for the few types that don't use the usual references. Any further functionality should go into an unspecialized subclass.
Approach 2 would be very verbose and hard to read. Approach 1 would be verbose as well, and since you would delegate nearly everything except the array definition to that traits class, you could as well use approach 3 since that is not too far away.
I think this template may help you:
template<typename T>
class traits
{
public:
typedef T * result;
};
template<>
class traits<int>
{
public:
typedef int result;
};
template<>
class traits<double>
{
public:
typedef double result;
};
traits<int>::result; // is int.
traits<char>::result; // is char *.
I am not sure how you want to implement set(T*,int). But for get you might want to try this
template<typename T, size_t Roz>
class Wektor
{
public:
template<typename U=T>
typename std::enable_if<std::is_arithmetic<U>::value, U>::type
Get(size_t n)
{
return tab[n];
}
template<typename U=T>
typename std::enable_if<!std::is_arithmetic<U>::value, U*>::type
Get(size_t n)
{
return &tab[n];
}
T tab[Roz];
};