Hello I wannted to build a helper class to initialize a stl valarray. What I would like is to do the following:
std::valarray<float> vec(3);
vlist_of<float>(vec)(2)(3)(5);
So I can just initialize the vectors at runtime using just one row command statement.
For doing the following I have tryed the following structure:
template <typename T>
struct vlist_of {
std::valarray<T>& data;
int i;
vlist_of(std::valarray<T>& _data):data(_data),i(0) {
(*this)(data);
}
vlist_of& operator()(std::valarray<T>& data){return *this;}
vlist_of& operator()(const T& t) {
data [i]=t;
i++;
return *this;
}
};
this structure works if I do the following :
vlist_of<float> tmp(vec);tmp(2)(3)(4);
Is it possible what I am asking ?
Yes. Make vlist_of a factory function:
template <typename T>
vlist_builder<T> vlist_of(std::valarray<T>& data)
{
return vlist_builder<T>(data);
}
Now it works http://liveworkspace.org/code/48aszl$0.
I'd personally prefer uniform initialization:
/*const*/ std::valarray<float> prefer { 2, 3, 5 };
See full sample:
#include <valarray>
#include <vector>
#include <iostream>
template <typename T>
struct vlist_builder
{
std::valarray<T>& data;
int i;
vlist_builder(std::valarray<T>& _data):data(_data),i(0) { }
vlist_builder& operator()(const T& t)
{
data[i++]=t;
return *this;
}
};
template <typename T>
vlist_builder<T> vlist_of(std::valarray<T>& data)
{
return vlist_builder<T>(data);
}
int main()
{
std::valarray<float> vec(3);
vlist_of<float>(vec)(2)(3)(5);
for(auto f : vec)
std::cout << f << "\n";
// prefer uniform initialization:
const std::valarray<float> prefer { 2, 3, 5 };
}
Related
I have a template class method
template<class T>
T pop<T>();
Now I want to do a template specialization as follows,
template<class T>
std::vector<T> pop<T>();
I can do the following no problem,
template<>
std::vector<int> classname::pop<std::vector<int>>();
But I still need to leave the type as a template parameter. How do I accomplish this?
Off the top of my head, I usually get around it by using a one-member struct:
template <typename T>
struct pop_impl {
static T pop(classname& x); // normal function
};
template <typename T>
struct pop_impl<std::vector<T>> {
static std::vector<T> pop(classname& x); // specialized for std::vector<T>
};
template <typename T>
T classname::pop() { return pop_impl<T>::pop(*this); }
This answer was originally provided by Austin Salgat in the body of the question Template Specialization for T -> std::vector, (posted under the CC BY-SA 3.0 license), and has been moved here as an answer in order to adhere to the site's Q&A format.
Thanks to Piotr I ended up using tag dispatching. Below is the code
for what I ended up doing,
// The public method that is accessed by class.push<std::vector<int>>(12);
template<class T>
void push(T data) {
push(tag<T>(), data);
}
// The private method that calls the actual vector push for vector types
template<class T>
void push(tag<std::vector<T>>, std::vector<T> const& data_vector) {
push_vector(data_vector);
}
// The actual implementation
template<class T>
void push_vector(std::vector<T> const& data_vector) {
// Actual implementation in here
}
A possible solution is a non-member function implemented like this
template <class T>
struct classname_pop
{
static T pop(classname &obj) { return obj.pop() ;}
}
template <class T>
struct classname_pop<std::vector<T>>
{
static std::vector<T> pop(classname &obj) {obj.specialized_pop() ;}
}
template <class T>
T classname_pop(classname &obj)
{
return classname_pop_t<T>::pop() ;
}
You need a temporary proxy to dispatch to different results:
Example:
#include <algorithm>
#include <iostream>
#include <vector>
class Stack
{
private:
std::vector<int> m_data;
class Pop {
friend class Stack;
public:
Stack& stack;
Pop(Stack& stack)
: stack(stack)
{}
private:
Pop(const Pop&) = default;
Pop& operator = (const Pop&) = default;
public:
operator int () {
std::vector<int>& data = stack.m_data;
int result = -1;
if( ! data.empty()) {
result = data.front();
data.erase(data.begin());
}
return result;
}
operator std::vector<int> () {
std::vector<int>& data = stack.m_data;
std::size_t size = std::min(data.size(), std::size_t(3));
std::vector<int> result(data.begin(), data.begin() + size);
data.erase(data.begin(), data.begin() + size);
return result;
}
};
public:
Stack()
: m_data( {0, 1, 2, 3, 4, 5, 6, 7, 8} )
{}
const std::vector<int>& data() const { return m_data; }
Pop pop() { return Pop(*this); }
};
int main()
{
Stack stack;
int i = stack.pop();
std::vector<int> v = stack.pop();
std::cout << "i = " << i << '\n';
std::cout << "v = {";
for(auto i : v)
std::cout << i;
std::cout << "}\n";
}
Disclaimer: I consider the code totally useless (It might become useful if there is a pop() just returning a single value and a pop(std::size_t) converting to different containers, where the destructor of Pop is doing the erase).
I want to find all objects of given types and add them to vector.
For now I have code:
template<class T>
void fill1(std::vector<Character*> &vec2)
{
for (int i = 0; i < GameObject::allObjects.size(); i++)
{
if (dynamic_cast<T>(GameObject::allObjects[i]))
{
vec2.push_back(dynamic_cast<Character*>(GameObject::allObjects[i]));
}
}
}
template<class First, class ...T>
void fill2(std::vector<Character*> &vec2)
{
fill1<First>(vec2);
fill2<T...>(vec2);
}
template<class ... T>
std::vector<Character*> SpecialList<T...>::get()
{
std::vector<Character*> vec2;
fill2<T...>(vec2);
return vec2;
}
The code doesn't compile at all.
The error we are getting is:
could not deduce template argument for 'First'
I know that all the given types are inherited from class Character and I have a vector of all my objects (GameObject::allObjects).
Instead of recursion use parameter pack expansion inside list initialization of a dummy array e.g.:
#include <vector>
#include <memory>
#include <tuple>
#include <iostream>
#include <algorithm>
template <class... Ts>
struct tag { };
template <class T>
struct Predicate {
template <class U>
bool operator()(std::shared_ptr<U> sp) const {
return std::dynamic_pointer_cast<T>(sp) != nullptr;
}
};
template <class... Ts, class T>
std::vector<std::shared_ptr<T>> all(std::vector<std::shared_ptr<T>> &v, tag<Ts...>) {
std::vector<std::shared_ptr<T>> result;
int dummy[] {(std::copy_if(v.begin(), v.end(), std::back_inserter(result), Predicate<Ts>{}),0)...};
static_cast<void>(dummy);
return result;
}
struct A {
virtual ~A() = default;
};
struct B: A { };
struct C: A { };
int main() {
std::vector<std::shared_ptr<A>> v { std::make_shared<A>(),
std::make_shared<A>(),
std::make_shared<B>(),
std::make_shared<B>(),
std::make_shared<C>(),
std::make_shared<C>() };
std::cout << all(v, tag<B, C>{}).size() << std::endl;
}
[live demo]
Is there any way to pass std::max_element() or std::min_element() to template class method? For example:
#include <vector>
#include <algorithms>
template <typename T>
class A
{
public:
int fooMax()
{
return foo(std::max_element());
}
int fooMin()
{
return foo(std::min_element());
}
private:
std::vector<T> data_;
private:
int foo(??? func)
{
auto it = func(data_.begin(), data_.end());
int i = do_something();
return i;
}
};
I tried to use function pointers, but it did not compiled.
std::max_element and std::min_element are template functions, and you need to instantiate them:
template <typename T>
class A
{
public:
int fooMax()
{
return foo(&std::max_element<typename std::vector<T>::const_iterator>);
}
int fooMin()
{
return foo(&std::min_element<typename std::vector<T>::const_iterator>);
}
private:
std::vector<T> data_;
private:
template<typename func_type>
int foo(func_type func)
{
auto it=func(data_.begin(), data_.end());
return 0;
}
};
Tested with gcc 5.3.1 with -std=c++14.
You may also choose to instantiate a std::vector<T>::iterator instead, if you so choose.
You can use the lambda expressions for this:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
struct A {
vector<T> v;
A(vector<T> v): v(v) { }
template <class Lambda>
T element(Lambda &&lambda) {
return *lambda(v.begin(), v.end());
}
};
int main() {
vector<int> vi {1, 2, 3, 4, 5, 6};
A<int> a(vi);
cout << a.element([](typename vector<int>::iterator begin,
typename vector<int>::iterator end){
return max_element(begin, end);
}) << endl;
}
This way it should get inlined and thus efficient...
If you can use c++14 code would get even simpler:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
struct A {
vector<T> v;
A(vector<T> v): v(v) { }
T element(auto &&lambda) {
return *lambda(v.begin(), v.end());
}
};
int main() {
vector<int> vi {1, 2, 3, 4, 5, 6};
A<int> a(vi);
cout << a.element([](auto begin, auto end) {
return max_element(begin, end);
}) << endl;
}
not what you want to see, I know. But if you want to pass it as a function pointer...
#include <vector>
#include <algorithm>
int do_something();
template <typename T>
class A
{
public:
int fooMax()
{
return foo(std::max_element<const_iterator>);
}
int fooMin()
{
return foo(std::min_element<const_iterator>);
}
private:
std::vector<T> data_;
private:
using const_iterator = typename std::vector<T>::const_iterator;
using fp = const_iterator (*)(const_iterator, const_iterator);
int foo(fp func)
{
auto it = func(data_.begin(), data_.end());
int i = do_something();
return i;
}
};
I have a template class method
template<class T>
T pop<T>();
Now I want to do a template specialization as follows,
template<class T>
std::vector<T> pop<T>();
I can do the following no problem,
template<>
std::vector<int> classname::pop<std::vector<int>>();
But I still need to leave the type as a template parameter. How do I accomplish this?
Off the top of my head, I usually get around it by using a one-member struct:
template <typename T>
struct pop_impl {
static T pop(classname& x); // normal function
};
template <typename T>
struct pop_impl<std::vector<T>> {
static std::vector<T> pop(classname& x); // specialized for std::vector<T>
};
template <typename T>
T classname::pop() { return pop_impl<T>::pop(*this); }
This answer was originally provided by Austin Salgat in the body of the question Template Specialization for T -> std::vector, (posted under the CC BY-SA 3.0 license), and has been moved here as an answer in order to adhere to the site's Q&A format.
Thanks to Piotr I ended up using tag dispatching. Below is the code
for what I ended up doing,
// The public method that is accessed by class.push<std::vector<int>>(12);
template<class T>
void push(T data) {
push(tag<T>(), data);
}
// The private method that calls the actual vector push for vector types
template<class T>
void push(tag<std::vector<T>>, std::vector<T> const& data_vector) {
push_vector(data_vector);
}
// The actual implementation
template<class T>
void push_vector(std::vector<T> const& data_vector) {
// Actual implementation in here
}
A possible solution is a non-member function implemented like this
template <class T>
struct classname_pop
{
static T pop(classname &obj) { return obj.pop() ;}
}
template <class T>
struct classname_pop<std::vector<T>>
{
static std::vector<T> pop(classname &obj) {obj.specialized_pop() ;}
}
template <class T>
T classname_pop(classname &obj)
{
return classname_pop_t<T>::pop() ;
}
You need a temporary proxy to dispatch to different results:
Example:
#include <algorithm>
#include <iostream>
#include <vector>
class Stack
{
private:
std::vector<int> m_data;
class Pop {
friend class Stack;
public:
Stack& stack;
Pop(Stack& stack)
: stack(stack)
{}
private:
Pop(const Pop&) = default;
Pop& operator = (const Pop&) = default;
public:
operator int () {
std::vector<int>& data = stack.m_data;
int result = -1;
if( ! data.empty()) {
result = data.front();
data.erase(data.begin());
}
return result;
}
operator std::vector<int> () {
std::vector<int>& data = stack.m_data;
std::size_t size = std::min(data.size(), std::size_t(3));
std::vector<int> result(data.begin(), data.begin() + size);
data.erase(data.begin(), data.begin() + size);
return result;
}
};
public:
Stack()
: m_data( {0, 1, 2, 3, 4, 5, 6, 7, 8} )
{}
const std::vector<int>& data() const { return m_data; }
Pop pop() { return Pop(*this); }
};
int main()
{
Stack stack;
int i = stack.pop();
std::vector<int> v = stack.pop();
std::cout << "i = " << i << '\n';
std::cout << "v = {";
for(auto i : v)
std::cout << i;
std::cout << "}\n";
}
Disclaimer: I consider the code totally useless (It might become useful if there is a pop() just returning a single value and a pop(std::size_t) converting to different containers, where the destructor of Pop is doing the erase).
I found the following code which I am using as a basis. It describes how to populate a boost::fusion::vector with the values 6:
#include <boost/fusion/algorithm.hpp>
#include <boost/fusion/container.hpp>
struct F {
F(int blah): blah(blah){}
template <typename T>
void operator()(T& t) const {
t = blah;
}
int blah;
};
template <typename T>
void apply_for_each_to_assign(T &t)
{
boost::fusion::for_each(t, F(6));
}
int main() {
boost::fusion::vector<int, double, int> idi;
apply_for_each_to_assign(idi);
}
My question is this, instead of populating every element with the value 6- what would be the neatest way to have every element incrementing by one? So
v[0] = 1
v[1] = 2
etc? I presume I would need to write an increment function but I am not sure how I need to incorporate it in to the above code?
You can use fold.
fold takes a function A f(A, B) where B is your element type, and a intial A value and call it on all the elements. It is rougly equivalent to f(f(f(initial, first_elem), second_elem), third_elem).
You should declare the functor like this:
struct accumulator
{
typedef int result_type;
template<typename T>
int operator()(int value, T& t) const
{
t += value;
return value + 1;
}
};
And here's the usage:
template <typename T>
void apply_for_each_to_assign(T &t)
{
boost::fusion::fold(t, 1, accumulator());
}
Here a whole example with printing:
#include <boost/fusion/algorithm/iteration/fold.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/include/fold.hpp>
#include <boost/fusion/container.hpp>
#include <iostream>
struct accumulator
{
typedef int result_type;
template<typename T>
int operator()(int value, T& t) const
{
t += value;
return value + 1;
}
};
struct Print {
template <typename T>
void operator()(T& t) const {
std::cout << t << std::endl;
}
};
template <typename T>
void apply_for_each_to_assign(T &t)
{
boost::fusion::fold(t, 1, accumulator());
boost::fusion::for_each(t, Print());
}
int main()
{
boost::fusion::vector<int, double, int> idi;
apply_for_each_to_assign(idi);
}