As an exercise for my personal enlightenment, I implement vector math with expression templates. I want to implement some operations that apply the same unary function to all elements to a vector expression. So far, I do this.
My base vector expression template is implemented like this
template <typename E>
class VectorExpr {
public:
int size() const { return static_cast<E const&>(*this).size(); }
float operator[](int i) const { return static_cast<E const&>(*this)[i]; }
operator E& () { return static_cast<E&>(*this); }
operator E const& () const { return static_cast<const E&>(*this); }
}; // class VectorExpr
Then, an object supposed to be a vector will look like this
class Vector2 : public VectorExpr<Vector2> {
public:
inline size_t size() const { return 2; }
template <typename E>
inline Vector2(VectorExpr<E> const& inExpr) {
E const& u = inExpr;
for(int i = 0; i < size(); ++i)
mTuple[i] = u[i];
}
private:
float mTuple[2];
};
Let's say I want to apply std::sin to all elements of an expression
template <typename E>
class VectorSin : public VectorExpr<VectorSin<E> > {
E const& mV;
public:
VectorSin(VectorExpr<E> const& inV) : mV(inV) {}
int size() const { return mV.size(); }
float operator [] (int i) const { return std::sin(mV[i]); }
};
Question => If I want to add more functions, I copy-paste what I do for the sin function, for every single function (like cos, sqrt, fabs, and so on). How I can avoid this kind of copy-pasting ? I tried things and figured out I'm still low in template-fu. No boost allowed ^^
template <typename F, typename E>
class VectorFunc : public VectorExpr<VectorFunc<F, E> > {
E const& mV;
public:
VectorSin(VectorExpr<E> const& inV) : mV(inV) {}
int size() const { return mV.size(); }
float operator [] (int i) const { return f(mV[i]); }
// this assumes the Functor f is default constructible, this is
// already not true for &std::sin. Adding the constructor that
// takes f, is left as an exercise ;)
F f;
};
In addition to the answer by pmr, The standard <cmath> functions aren't functors, so you couldn't use them directly to specify unique specialisations of your class - i.e. you wouldn't have a separate template instantiation for std::sin versus std::cos (which is what I gather you're aiming for? correct me if I've misunderstood you on that).
You could create a wrapper in order to map a function pointer to a distinct type, e.g.
#include <iostream>
template< void (*FuncPtr)() > struct Func2Type
{
void operator() () { FuncPtr(); }
};
void Hello() { std::cout << "Hello" << std::endl; }
void World() { std::cout << "world" << std::endl; }
int main()
{
Func2Type<Hello> test1;
Func2Type<World> test2;
test1();
test2();
}
That way you could use them as template arguments in the same way as a normal functor class
Related
I've got this Map in my Entity-Component-System:
std::map<u_int32_t, std::vector<std::shared_ptr<Component>>> _componentMap;
The u_int32_t is the key to a vector of components. There can be multiple instances of the same component. (That's why there's a vector).
Now I would like to have a templated getter-function that returns a Vector of an inherited type:
template<class T> inline const std::vector<std::shared_ptr<T>> & getVector() const
{
u_int32_t key = getKey<T>();
return static_cast<std::vector<std::shared_ptr<T>>>(_componentMap.count(key) ? _componentMap.at(key) : _emptyComponentVec);
}
I know that this doesn't work, since std::vectors of different types are completely unrelated and I cannot cast between them. I would also like to avoid allocating a new vector every time this function is called.
But how I can I get the desired behaviour? When the the components are added I can create an std::vector of the desired derived type.
The question could also be: How can I have an std::map containing different types of std::vector?
For any solutions I can not link against boost, though if absolutely needed, I could integrate single headers of boost.
template<class It>
struct range_view {
It b, e;
It begin() const { return b; }
It end() const { return e; }
using reference = decltype(*std::declval<It const&>());
reference operator[](std::size_t n) const
{
return b[n];
}
bool empty() const { return begin()==end(); }
std::size_t size() const { return end()-begin(); }
reference front() const {
return *begin();
}
reference back() const {
return *std::prev(end());
}
template<class O>
range_view( O&& o ):
b(std::begin(o)), e(std::end(o))
{}
};
this is a quick range view. It can be improved.
Now all you need to do is write a pseudo-random-access iterator that converts its arguments. So it takes a random access iterator over a type T, then does some operation F to return a type U. It forwards all other operations.
The map then stores std::vector<std::shared_ptr<Base>>. The gettor returns a range_view< converting_iterator<spBase2spDerived> >.
Here is a crude implementation of a solution I have in mind for this problem. Of course, there are many rooms to refine the code, but hopefully it conveys my idea.
#include <iostream>
#include <map>
#include <vector>
#include <memory>
using namespace std;
class Base {
public:
virtual void f() const = 0;
};
class A : public Base {
public:
static const int type = 0;
explicit A(int a) : a_(a) {}
void f() const { cout << "calling A::f" << endl;}
int a_;
};
class B : public Base {
public:
static const int type = 1;
explicit B(int a) : a_(a) {}
void f() const { cout << "calling B::f" << endl;}
int a_;
};
class MapWrapper {
public:
template<class T>
void append(int a, vector<T> const& vec) {
types_[a] = T::type;
my_map_[a] = make_shared<vector<T>>(vec);
}
template<class T>
vector<T> const& get(int a) const {
return *static_pointer_cast<vector<T>>( my_map_.at(a) );
}
map<int, shared_ptr<void>> const& get_my_map() const {
return my_map_;
}
vector<shared_ptr<Base>> get_base(int a) const {
vector<shared_ptr<Base>> ret;
switch(types_.at(a)) {
case 0: {
auto const vec = get<A>(a);
for(auto v : vec)
ret.push_back(make_shared<A>(v));
break;
}
case 1: {
auto const vec = get<B>(a);
for(auto v : vec)
ret.push_back(make_shared<B>(v));
break;
}
}
return ret;
}
map<int, shared_ptr<void>> my_map_;
map<int, int> types_;
};
int main() {
MapWrapper map_wrapper;
map_wrapper.append(10, vector<A>{A(2), A(4)});
map_wrapper.append(20, vector<B>{B(5), B(7), B(9)});
for(auto const& w : map_wrapper.get_my_map())
for(auto v : map_wrapper.get_base(w.first))
v->f();
for(auto const& x: map_wrapper.get<A>(10))
cout << x.a_ << " ";
cout << endl;
for(auto const& x: map_wrapper.get<B>(20))
cout << x.a_ << " ";
return 0;
}
The solution was to use reinterpret_cast:
template<class T> inline std::vector<std::shared_ptr<T>> * getVector() const
{
auto key = getKey<T>();
return reinterpret_cast<std::vector<std::shared_ptr<T>> *>( (_componentMap.count(key) ? _componentMap.at(key).get() : const_cast<std::vector<std::shared_ptr<Component>> *>(&_emptyComponentSharedPtrVec)) );
}
It's not very pretty but it does work fine and it fulfills all requirements.
In C++, we can pass a function/functor to a function like so:
template <typename F>
void doOperation(int a, int b, F f){
std::cout << "Result: " << f(a,b) << std::endl;
}
we can then use both functions and functors:
int add(const int &a, const int &b){ return a+b; }
struct subtract(){
void operator() (const int &a, const int &b) { return a-b; }
};
and use it in the following manner:
doOperation(1,2,add);
doOperation(5,2,subtract());
My question is, can I do something similar with a class and pass a function as an argument to a class, store it and use it later? E.g.
template <typename F>
class doOperation{
public:
doOperation(int &a, int &b, F f) : a(a), b(b), f(f) {};
void setOperands(int &a, int &b) { this->a = a; this->b = b };
void performCalculation(){
std::cout << "Result: " << f(a,b) << std::endl;
}
private:
int a,b;
F f;
}
So that we may assign it a function once and then later use it:
doOperation summing(1,2,add);
summing.setOperands(2,3);
summing.performCalculation();
doOperation subtraction(7,3,subtract());
subtraction.performCalculation();
If my examples are valid, I would appreciate the explanation for the mechanics here as I seem to be getting a bit lost. In case I missed something, I am looking for hints on whether this can be achieved.
Lastly, how would I then use such a class doOperation in other functions and classes. For example, would defining something like this inside a member function require me to template the new class, its member function, and how would it be declared and used:
class higherFunctionality{
public:
higherFunctionality() {...}
void coolThings(){
doOperation *myOperation = operationFactory( ... );
myOperation->setOperands(4,5);
myOperation->performCalculation();
}
};
Yes, but you have to supply the type when you instantiate template classes. The usual way to deal with this is to create a helper function:
template < typename Fun > struct operation_class
{
operation_class(Fun f) : fun{f} {}
Fun fun;
};
template < typename Fun >
operation_class<Fun> operation(Fun fun) { return operation_class<Fun>{fun}; }
int main()
{
auto op0 = operation(some_fun);
auto op1 = operation(some_functor{});
}
Frankly though, you are better off just using lambda:
auto op0 = [a,b]() { return sum(a,b); };
auto op1 = [a,b]() { return subtract{a,b}(); }
// C++17:
auto op2 = [op=subtract{a,b}] { return op(); };
I have to use a function in library with variable parameters (createObject), the general usage is:
Class Point
{
public:
Point() {};
int x;
int y;
const char* name;
}
int main()
{
Point p;
createObject("%d",p.x,"%f",p.y,"%d",1,"%s",p.name);
}
Now i want to generalize usage of this function with Macro and Template, like this:
#define PARAM_Matrix(obj) "%d",obj.m,"%d",obj.n,"%d %d",obj[0][0],"%d %d",obj[0][1],"%d %d",obj[0][2]
#define PARAM_Person(obj) "%d",obj.age,"%s",obj.name
#define PARAM_Point(obj) "%d",obj.x,"%f",obj.y,"%d",1,"%s",obj.name
#define MAKE_PARAM(className,obj) PARAM_##className(obj)
class Person;
class Matrix;
class Point
{
public:
Point() {};
int x;
int y;
const char* name;
}
template<typename T> createGeneralize(T t)
{
return createObject(MAKE_PARAM(T,t));
}
int main()
{
Person per;
Matrix m;
Point p;
createGeneralize<Person>(per);
createGeneralize<Matrix>(m);
createGeneralize<Point>(p);
}
I expected that in createGeneralize() the C++ compiler expanding the macro to MAKE_PARAM(Point,t) (or MAKE_PARAM(Matrix,t)...). However, it is not the case, it always expands to MAKE_PARAM(T).
Your idea is not feasible because the preprocessor macros are converted to text before actual compiling. while the template arguments are substituted during compilation. so you get something like:
doMore (Point p)
{
T u, v; u = v;
}
i suggest just use templates.
Instead of macro, you may use template:
auto as_tuple(const Person& obj) { return std::make_tuple("%d", obj.age, "%s", obj.name); }
auto as_tuple(const Matrix& obj) { return std::make_tuple("%d", obj.m,"%d",obj.n,"%d %d",obj.obj[0][0],"%d %d",obj.obj[0][1],"%d %d",obj.obj[0][2]); }
auto as_tuple(const Point& obj) { return std::make_tuple("%d", obj.x,"%f",obj.y,"%d",1,"%s",obj.name); }
template<typename Tuple, std::size_t...Is>
void createGeneralize(const Tuple& t, std::index_sequence<Is...>)
{
return createObject(std::get<Is>(t)...);
}
template<typename T> void createGeneralize(const T& t)
{
const auto& tuple = as_tuple(t);
return createGeneralize(tuple, std::make_index_sequence<std::tuple_size<std::decay_t<decltype(tuple)>>::value>());
}
Live example
I have this structure of classes.
class Interface {
// ...
};
class Foo : public Interface {
// ...
};
template <class T>
class Container {
// ...
};
And I have this constructor of some other class Bar.
Bar(const Container<Interface> & bar){
// ...
}
When I call the constructor this way I get a "no matching function" error.
Container<Foo> container ();
Bar * temp = new Bar(container);
What is wrong? Are templates not polymorphic?
I think the exact terminology for what you need is "template covariance", meaning that if B inherits from A, then somehow T<B> inherits from T<A>. This is not the case in C++, nor it is with Java and C# generics*.
There is a good reason to avoid template covariance: this will simply remove all type safety in the template class. Let me explain with the following example:
//Assume the following class hierarchy
class Fruit {...};
class Apple : public Fruit {...};
class Orange : public Fruit {...};
//Now I will use these types to instantiate a class template, namely std::vector
int main()
{
std::vector<Apple> apple_vec;
apple_vec.push_back(Apple()); //no problem here
//If templates were covariant, the following would be legal
std::vector<Fruit> & fruit_vec = apple_vec;
//push_back would expect a Fruit, so I could pass it an Orange
fruit_vec.push_back(Orange());
//Oh no! I just added an orange in my apple basket!
}
Consequently, you should consider T<A> and T<B> as completely unrelated types, regardless of the relation between A and B.
So how could you solve the issue you're facing? In Java and C#, you could use respectively bounded wildcards and constraints:
//Java code
Bar(Container<? extends Interface) {...}
//C# code
Bar<T>(Container<T> container) where T : Interface {...}
The next C++ Standard (known as C++1x (formerly C++0x)) initially contained an even more powerful mechanism named Concepts, that would have let developers enforce syntaxic and/or semantic requirements on template parameters, but was unfortunately postponed to a later date. However, Boost has a Concept Check library that may interest you.
Nevertheless, concepts might be a little overkill for the problem you encounter, an using a simple static assert as proposed by #gf is probably the best solution.
* Update: Since .Net Framework 4, it is possible to mark generic parameters has being covariant or contravariant.
There are two problems here: default constructions have the form MyClass c;; with parentheses it looks like a function declaration to the compiler.
The other problem is that Container<Interface> is simply a different type then Container<Foo> - you could do the following instead to actually get polymorphism:
Bar::Bar(const Container<Interface*>&) {}
Container<Interface*> container;
container.push_back(new Foo);
Bar* temp = new Bar(container);
Or of course you could make Bar or its constructor a template as Kornel has shown.
If you actually want some type-safe compile-time polymorphism, you could use Boost.TypeTraits is_base_of or some equivalent:
template<class T>
Bar::Bar(const Container<T>& c) {
BOOST_STATIC_ASSERT((boost::is_base_of<Interface, T>::value));
// ... will give a compile time error if T doesn't
// inherit from Interface
}
No. Imagine that the container parameter is "hardcoded" into the class it defines (and that is actually how it works). Hence the container type is Container_Foo, that is not compatible with Container_Interface.
What you might try however is this:
template<class T>
Bar(const Container<T> & bar){
...
}
Yet you loose direct type checking that way.
Actually the STL way (probably more effective and generic) would be to do
template<class InputIterator>
Bar(InputIterator begin, InputIterator end){
...
}
... but I assume you don't have iterators implemented in the container.
It is possible to create an inheritance tree for containers, reflecting the inheritance tree of the data. If you have the following data:
class Interface {
public:
virtual ~Interface()
{}
virtual void print() = 0;
};
class Number : public Interface {
public:
Number(int value) : x( value )
{}
int get() const
{ return x; }
void print()
{ std::printf( "%d\n", get() ); };
private:
int x;
};
class String : public Interface {
public:
String(const std::string & value) : x( value )
{}
const std::string &get() const
{ return x; }
void print()
{ std::printf( "%s\n", get().c_str() ); }
private:
std::string x;
};
You could also have the following containers:
class GenericContainer {
public:
GenericContainer()
{}
~GenericContainer()
{ v.clear(); }
virtual void add(Interface &obj)
{ v.push_back( &obj ); }
Interface &get(unsigned int i)
{ return *v[ i ]; }
unsigned int size() const
{ return v.size(); }
private:
std::vector<Interface *> v;
};
class NumericContainer : public GenericContainer {
public:
virtual void add(Number &obj)
{ GenericContainer::add( obj ); }
Number &get(unsigned int i)
{ return (Number &) GenericContainer::get( i ); }
};
class TextContainer : public GenericContainer {
public:
virtual void add(String &obj)
{ GenericContainer::add( obj ); }
String &get(unsigned int i)
{ return (String &) GenericContainer::get( i ); }
};
This is not the best performing code; it is just to give an idea. The only problem with this approach is that every time you add a new Data class, you have to also create a new Container. Apart from that, you have polymorphism "working again". You can be specific or general:
void print(GenericContainer & x)
{
for(unsigned int i = 0; i < x.size(); ++i) {
x.get( i ).print();
}
}
void printNumbers(NumericContainer & x)
{
for(unsigned int i = 0; i < x.size(); ++i) {
printf( "Number: " );
x.get( i ).print();
}
}
int main()
{
TextContainer strContainer;
NumericContainer numContainer;
Number n( 345 );
String s( "Hello" );
numContainer.add( n );
strContainer.add( s );
print( strContainer );
print( numContainer );
printNumbers( numContainer );
}
I propose the following workaround, which employs a template function. Although the example use Qt's QList, nothing prevents the solution from being straightforwardly transposed to any other container.
template <class D, class B> // D (Derived) inherits from B (Base)
QList<B> toBaseList(QList<D> derivedList)
{
QList<B> baseList;
for (int i = 0; i < derivedList.size(); ++i) {
baseList.append(derivedList[i]);
}
return baseList;
}
Pros:
general
type-safe
fairly efficient if the items are pointers or some other cheaply copy-constructible elements (such as implicitly shared Qt classes)
Cons:
requires the creation of a new container, as opposed to enabling the reuse of the original one
implies some memory and processor overhead both to create and to populate the new container, which depend heavily on the cost of the copy-constructor
#include <iostream>
#include <sstream>
#include <map>
#include <vector>
struct Base { int b = 111; };
struct Derived: public Base { };
struct ObjectStringizer {
template <typename T>
static std::string to_string(const T& t) {
return helper<T>()(t);
}
template <typename T, typename = void>
struct helper {
std::string operator()(const T& t) {
std::ostringstream oss;
oss << t;
return oss.str();
}
};
template <typename T>
struct helper<T, typename std::enable_if<std::is_base_of<Base, T>::value>::type> {
std::string operator()(const T& base) {
return to_string(base.b);
}
};
template <typename T>
struct helper<std::vector<T>> {
std::string operator()(const std::vector<T>& v) {
std::ostringstream oss;
for (size_t i = 0, sz = v.size(); i < sz; ++i) {
oss << (i ? "," : "") << to_string(v[i]);
}
return "[" + oss.str() + "]";
}
};
template <typename Key, typename Value>
struct helper<std::map<Key, Value>> {
std::string operator()(const std::map<Key, Value>& m) {
std::ostringstream oss;
for (auto iter = m.begin(), iter_end = m.end(); iter_end != iter; ++iter) {
oss << (m.begin() != iter ? "," : "") << to_string(iter->first) << ":" << to_string(iter->second);
}
return "{" + oss.str() + "}";
}
};
};
int main(int argc, char* argv[]) {
std::cout << ObjectStringizer::to_string("hello ") << ObjectStringizer::to_string(std::string("world")) << std::endl;
std::cout << ObjectStringizer::to_string(Derived()) << std::endl;
std::cout << ObjectStringizer::to_string(std::vector<int>{3, 5, 7, 9}) << std::endl;
std::cout << ObjectStringizer::to_string(std::map<int, std::string>{{1, "one"}, {2, "two"}}) << std::endl;
return 0;
}
container is a container of Foo objects not a container of Interface objects
And it cannot be polymorphic either, pointers to things can be ,but not the objects themselvs. How big would the slots in the container have to be for container if you could put anything derived from interface in it
you need
container<Interface*>
or better
container<shared_ptr<Interface> >
Given the following:
struct Foo
{
int bar() const;
};
struct IsEqual : public std::unary_function<Foo*, bool>
{
int val;
IsEqual(int v) : val(v) {}
bool operator()(const Foo* elem) const
{
return elem->bar() == val;
}
};
I have a container of Foo* and I use std::find_if and std::not1 to find out if there are any elements in the container where bar() returns something different from a given value. The code looks like this:
// Are all elements equal to '2'?
bool isAllEqual(const std::vector<Foo*> &vec)
{
return find_if(vec.begin(), vec.end(), std::not1(IsEqual(2))) == vec.end();
}
Fast-forward into the future and I now have a different container, this time containing std::tr1::shared_ptr<Foo>. I'd love to simply re-use my functor in an overloaded version of isAllEqual(). But I can't. Foo* and shared_ptr<Foo> are different types. And I need to inherit from unary_function so I can use not1. It'd be more elegant if I could avoid writing the same functor twice.
Questions:
Is there any way to write IsEqual so it can use both raw and smart pointers?
Did I handcuff myself by using std::not1? Should I just write IsNotEqual instead?
Restrictions:
I can't use anything from the boost library.
Our compiler isn't cool enough to support C++0x lambdas.
How about:
template<typename T>
struct IsEqual : public std::unary_function<const T&, bool>
{
int val;
IsEqual(int v) : val(v) {}
bool operator()(const T& elem) const
{
return elem->bar() == val;
}
};
template<typename T>
IsEqual<T> DeduceEqualityComparer(int v, T) { return IsEqual<T>(v); }
// Are all elements equal to '2'?
template<typename TContainer>
bool isAllEqual(const TContainer& coll)
{
using std::begin; // in C++0x, or else write this really simple function yourself
using std::end;
if (begin(coll) == end(coll)) return true;
return find_if(begin(coll), end(coll), std::not1(DeduceEqualityComparer(2, *begin(coll)))) == end(coll);
}
// --*-- C++ --*--
#include <vector>
#include <algorithm>
#include <iostream>
// Template unary function example.
template <typename T>
struct IsEqual : public std::unary_function<T, bool>
{
int v;
IsEqual (int v) : v (v) {}
bool operator () (const T & elem) const
{
return elem ? elem->bar () == v : false;
}
};
// Generic algorithm implementation example...
template <typename T1, typename T2>
bool isAllEqual (const T1 & c, T2 v)
{
return find_if (
c.begin (), c.end (),
std::not1 (IsEqual <typename T1::value_type> (v))) == c.end ();
}
// Some arbitrary pointer wrapper implementation,
// provided just for an example, not to include any
// specific smart pointer implementation.
template <typename T>
class WrappedPtr
{
const T *v;
public:
typedef void (WrappedPtr<T>::*unspecified_boolean_type) () const;
WrappedPtr (const T *v) : v (v) {}
const T *operator -> () const { return v; }
operator unspecified_boolean_type () const
{
return v != NULL ?
&WrappedPtr<T>::unspecified_boolean_true : NULL;
}
private:
void unspecified_boolean_true () const {}
};
// Example of structure that could be used with our algorithm.
struct Foo
{
int v;
Foo (int v) : v (v) {}
int bar () const
{
return v;
}
};
// Usage examples...
int main ()
{
Foo f1 (2), f2 (2);
// Example of using raw pointers...
{
std::vector<Foo *> vec;
vec.push_back (NULL);
vec.push_back (&f1);
vec.push_back (&f2);
if (isAllEqual (vec, 2))
std::cout << "All equal to 2" << std::endl;
else
std::cout << "Not all equal to 2" << std::endl;
}
// Example of using smart pointers...
{
std::vector< WrappedPtr<Foo> > vec;
vec.push_back (NULL);
vec.push_back (&f1);
vec.push_back (&f2);
if (isAllEqual (vec, 2))
std::cout << "All equal to 2" << std::endl;
else
std::cout << "Not all equal to 2" << std::endl;
}
}
My shot would be something like this:
template<typename PtrToFoo>
struct IsEqual : public std::unary_function<PtrToFoo, bool>
{
int val;
IsEqual(int v) : val(v) {}
bool operator()(PtrToFoo elem) const
{
return elem->bar() == val;
}
};
You'll have a different operator() instantiation for everything dereferencable with ->, so raw pointers and smart pointers.
You could maybe do something tricky with implicit conversions:
class IsEqualArg {
public:
// Implicit conversion constructors!
IsEqualArg(Foo* foo) : ptr(foo) {}
IsEqualArg(const std::tr1::shared_ptr<Foo>& foo) : ptr(&*foo) {}
private:
Foo* ptr;
friend struct IsEqual;
};
struct IsEqualArg : public std::unary_function<IsEqualArg, bool> {
bool operator()( const IsEqualArg& arg ) const;
//...
};
But I'd really rather just write a IsNotEqual.
Ben's answer is really the only thing you can do in c++03. In C++0x though, and/or with boost::bind, you don't need to inherit from unary_function. This allows you to use a templated () operator. You can usually get away with the same in C++03 but I think that it's technically incorrect to do so.