I wrote an expression template to sum up to three vectors together. However, as you can see in my code, this doesn't scale very well because for every additional sum operand I have to add another nested template expression. Is there a way to refactor this code to handle a (theoretically) infinite amount of additions?
template<class A>
struct Expr {
operator const A&() const {
return *static_cast<const A*>(this);
}
};
template<class A, class B>
class Add : public Expr<Add<A,B>> {
private:
const A &a_;
const B &b_;
public:
Add(const A &a, const B &b) : a_(a), b_(b) { }
double operator[] (int i) const {
return a_[i] + b_[i];
}
};
class Vector : public Expr<Vector> {
private:
double *data_;
int n_;
public:
Vector(int n, double w = 0.0) : n_(n) {
data_ = new double[n];
for(int i = 0; i < n; ++i) {
data_[i] = w;
}
}
double operator[] (int i) const {
return data_[i];
}
friend Expr<Add<Vector, Vector>> operator+(Vector &a, Vector &b) {
return Add<Vector, Vector>(a, b);
}
friend Expr<Add<Add<Vector, Vector>, Vector>> operator+(const Add<Vector, Vector> &add, const Vector &b) {
return Add<Add<Vector, Vector>, Vector>(add, b);
}
template<class A>
void operator= (const Expr<A> &a) {
const A &a_(a);
for(int i = 0; i < n_; ++i) {
data_[i] = a_[i];
}
}
};
int main() {
constexpr int size = 5;
Vector a(size, 1.0), b(size, 2.0), c(size);
c = a + b + a;
return 0;
}
This was working for me:
class Vector : public Expr<Vector> {
private:
double *data_;
int n_;
public:
Vector(int n, double w = 0.0) : n_(n) {
data_ = new double[n];
for(int i = 0; i < n; ++i) {
data_[i] = w;
}
}
double operator[] (int i) const {
return data_[i];
}
template<class A, class B>
friend Add<A, B> operator+(const Expr<A> &a, const Expr<B> &b) {
return Add<A, B>(a, b);
}
template<class A>
void operator= (const Expr<A> &a) {
const A &a_(a);
for(int i = 0; i < n_; ++i) {
data_[i] = a_[i];
}
}
};
I'm no template wizard (and I'm not up-to-date with the latest possibilities), but you can at least make a function that added a variadic amount of vectors, using something like described in the code below.
You could then buildup you expressiontree like you did before and call this function in you evaluation (operator=) function.
edit: updated the code, based on this solution (credits there)
#include <vector>
#include <algorithm>
template<typename T>
using Vec = std::vector<T>;
template<typename T, typename...Args>
auto AddVector_impl(Vec<Args> const & ... vecs){
auto its = std::tuple(cbegin(vecs)...);
auto add_inc = [](auto&... iters){
return ((*iters++) + ... );
};
auto end_check = [&](auto&...iters){
return ((iters != cend(vecs)) && ...);
};
Vec<T> res;
for(auto it = back_inserter(res); apply(end_check,its);){
*it++ = apply(add_inc,its);
}
return res;
}
template<typename T, typename... Args>
Vec<T> AddVector(Vec<T> const& vt, Vec<Args> const&... vargs){
return AddVector_impl<T>(vt,vargs...);
}
#include <iostream>
int main() {
constexpr auto size = 5;
Vec<double> a(size, 1.0), b(size, 2.0);
auto c = AddVector(a, b, a);
for(auto const& el : c){
std::cout << el << " ";
}
}
outputs:
4 4 4 4 4
Related
Following the question in Pointer to portions of array, a structure that does operations with portions of an array was proposed.
I would like to request one further question within this issue.
I would like to create a structure for blockMatrices using std::vector and would require to change the implementation of the structure for getting a 3x3 matrix out of a 4x4 matrix.
The current test case is:
#include <vector>
#include <array>
#include <iostream>
// define matrix 4x4
typedef std::array<double, 16> matrix4;
// define matrix 3x3
typedef std::array<double, 9> matrix3;
// get 3x3 matrix out of a 4x4 matrix
struct subMat
{
matrix4& matrix_;
const double& operator[](size_t index) const
{
static size_t mapping[] = {0, 1, 2, 4, 5, 6, 8, 9, 10};
return matrix_[mapping[index]];
}
subMat (matrix4& A): matrix_(A){}
};
template <typename T>
double sum_of_elements(const T& arr)
{
double res = 0;
for (int i=0;i < 9; ++i)
{
res += arr[i];
}
return res;
}
int main(int argCount, char *args[])
{
std::vector<matrix4> myBlockMatrix(5);
for (int i=0; i < myBlockMatrix.size(); i++)
{
for (int j = 0; j<myBlockMatrix[0].size(); j++)
{
myBlockMatrix[i][j] = i*j;
}
}
for (int i = 0; i<myBlockMatrix.size(); i++)
{
std::cout << sum_of_elements(subMat(myBlockMatrix[i])) << std::endl; // this works
}
subBlockMatrix subBlock (myBlockMatrix);
for (int i = 0; i<myBlockMatrix.size(); i++)
{
std::cout << sum_of_elements(subBlock[i])) << std::endl;
}
return 0;
}
For overloading the [] operator, I have:
struct subBlockMatrix : std::vector<matrix4>
{
std::vector<matrix4>& blockMatrix_;
const matrix4& operator[](std::size_t index) const
{
static size_t mapping[] = {0, 1, 2, 4, 5, 6, 8, 9, 10};
return blockMatrix_[mapping[index]];
}
subBlockMatrix(std::vector<matrix4>& A) : blockMatrix_(A) {}
};
But this does not work...
I am having difficulty understanding how to make it work and would really appreciate the help!
Best Regards
I'd start with a matrix view, which starts with an array view.
#include <vector>
#include <iostream>
template<class T, class Size=std::size_t, class Stride=Size>
struct array_view {
array_view( T* start, Size sz, Stride s ):
b(start), length(sz), stride(s) {}
array_view( T* start, Size sz = {} ):
b(start), length(sz), stride(sz) {}
array_view() = default;
array_view( T* start, T* finish ):
array_view(start, finish-start) {}
T* begin() const { return b; }
T* end() const { return b+length; }
std::size_t size() const { return length; }
bool empty() const { return size() == 0; }
explicit operator bool() const { return b; }
T& operator[]( std::size_t i ) const { return begin()[i]; }
array_view& operator++() {
*this += 1;
return *this;
}
array_view operator++(int)& {
auto self = *this;
++this;
return self;
}
array_view& operator--() {
*this -= 1;
return *this;
}
array_view operator--(int)& {
auto self = *this;
--this;
return self;
}
array_view& operator+=(std::ptrdiff_t delta)&{
b+=delta*length;
return *this;
}
array_view& operator-=(std::ptrdiff_t delta)&{
b-=delta*length;
return *this;
}
friend array_view operator+(array_view self, std::ptrdiff_t delta) {
self += delta;
return self;
}
friend array_view operator-(array_view self, std::ptrdiff_t delta) {
self -= delta;
return self;
}
friend array_view operator+(std::ptrdiff_t delta, array_view self) {
self += delta;
return self;
}
friend array_view operator-(std::ptrdiff_t delta, array_view self) {
self -= delta;
return self;
}
// checks address, not contents
friend bool operator==(array_view const& lhs, array_view const& rhs) {
return lhs.b == rhs.b && lhs.length == rhs.length && lhs.stride == rhs.stride;
}
friend bool operator!=(array_view const& lhs, array_view const& rhs) {
return !(lhs==rhs);
}
private:
T* b = nullptr;
Size length = {};
Stride stride = {};
};
then we get a matrix_view. First we write an index_iterator for an iterator wrapper around something that is a value (like a sequence of rows or columns, or an integer):
template<class V>
struct index_iterator {
index_iterator(V v):value(v) {}
V const& operator*() const& { return value; }
V& operator*()& { return value; }
V operator*()&& { return std::move(value); }
V* operator->() { return std::addressof(value); }
V const* operator->() const { return std::addressof(value); }
friend bool operator==(index_iterator const& lhs, index_iterator const& rhs ) {
return lhs.value==rhs.value;
}
friend bool operator!=(index_iterator const& lhs, index_iterator const& rhs ) {
return lhs.value!=rhs.value;
}
index_iterator& operator++() {
++value;
return *this;
}
index_iterator operator++(int)& {
auto self = *this;
++value;
return self;
}
index_iterator& operator--() {
--value;
return *this;
}
index_iterator operator--(int)& {
auto self = *this;
--value;
return self;
}
index_iterator& operator+=( std::ptrdiff_t delta )& {
value += delta;
return *this;
}
index_iterator& operator-=( std::ptrdiff_t delta )& {
value -= delta;
return *this;
}
friend index_iterator operator+(index_iterator self, std::ptrdiff_t delta) {
self += delta;
return self;
}
friend index_iterator operator-(index_iterator self, std::ptrdiff_t delta) {
self -= delta;
return self;
}
friend index_iterator operator+(std::ptrdiff_t delta, index_iterator self) {
self += delta;
return self;
}
friend index_iterator operator-(std::ptrdiff_t delta, index_iterator self) {
self -= delta;
return self;
}
V operator[](std::size_t i)const {
return *((*this) + i);
}
private:
V value = {};
};
template<class T, class M=std::size_t, class Stride=M, class N=M>
struct matrix_view {
using row_view = array_view<T, N, Stride>;
matrix_view( T* start, M cols={}, Stride stride = {}, N rows={} ):
b(start), m(cols), s(stride), n(rows)
{}
matrix_view() = default;
index_iterator<row_view> begin() const { return {{b, n, s}}; }
index_iterator<row_view> end() const { return begin()+m; }
std::size_t size() const { return m; }
bool empty() const { return size() == 0; }
explicit operator bool() const { return b; }
row_view operator[]( std::size_t i ) const { return begin()[i]; }
private:
T* b = nullptr;
M m = {};
Stride s = {};
N n = {};
};
template<std::size_t N>
using size = std::integral_constant<std::size_t, N>;
int main(){
std::vector<int> v {00,01,02,03, 10,11,12,13, 20,21,22,23, 30,31,32,33};
matrix_view<int, size<3>, size<4>> m = v.data()+5;
for (auto col:m) {
for (auto e:col) {
std::cout << e << ",";
}
std::cout << "\n";
}
}
and then clean it up with some CRTP DRY and EBO.
But that is just me.
Live example.
Say I have a nest for loop like
for (int x = xstart; x < xend; x++){
for (int y = ystart; y < yend; y++){
for (int z = zstart; z < zend; z++){
function_doing_stuff(std::make_tuple(x, y, z));
}
}
}
and would like to transform it into
MyRange range(xstart,xend,ystart,yend, zstart,zend);
for (auto point : range){
function_doing_stuff(point);
}
How would I write the MyRange class to be as efficient as the nested for loops?
The motivation for this is to be able to use std algorithms (such as transform, accumulate, etc), and to create code that is largely dimension agnostic.
By having an iterator, it would be easy to create templated functions that operate over a range of 1d, 2d or 3d points.
Code base is currently C++14.
EDIT:
Writing clear questions is hard. I'll try to clarify.
My problem is not writing an iterator, that I can do. Instead, the problem is one of performance: Is it possible to make an iterator that is as fast as the nested for loops?
With range/v3, you may do
auto xs = ranges::view::iota(xstart, xend);
auto ys = ranges::view::iota(ystart, yend);
auto zs = ranges::view::iota(zstart, zend);
for (const auto& point : ranges::view::cartesian_product(xs, ys, zs)){
function_doing_stuff(point);
}
You can introduce your own class as
class myClass {
public:
myClass (int x, int y, int z):m_x(x) , m_y(y), m_z(z){};
private:
int m_x, m_y, m_z;
}
and then initialize a std::vector<myClass> with your triple loop
std::vector<myClass> myVec;
myVec.reserve((xend-xstart)*(yend-ystart)*(zend-zstart)); // alloc memory only once;
for (int x = ystart; x < xend; x++){
for (int y = xstart; y < yend; y++){ // I assume you have a copy paste error here
for (int z = zstart; z < zend; z++){
myVec.push_back({x,y,z})
}
}
}
Finally, you can use all the nice std algorithms with the std::vector<myClass> myVec. With the syntactic sugar
using MyRange = std::vector<MyClass>;
and
MyRange makeMyRange(int xstart, int xend, int ystart, int yend, int zstart,int zend) {
MyRange myVec;
// loop from above
return MyRange;
}
you can write
const MyRange range = makeMyRange(xstart, xend, ystart, yend, zstart, zend);
for (auto point : range){
function_doing_stuff(point);
}
With the new move semantics this wont create unneeded copies. Please note, that the interface to this function is rather bad. Perhaps rather use 3 pairs of int, denoting the x,y,z interval.
Perhaps you change the names to something meaningful (e.g.myClass could be Point).
Another option, which directly transplants whatever looping code, is to use a Coroutine. This emulates yield from Python or C#.
using point = std::tuple<int, int, int>;
using coro = boost::coroutines::asymmetric_coroutine<point>;
coro::pull_type points(
[&](coro::push_type& yield){
for (int x = xstart; x < xend; x++){
for (int y = ystart; y < yend; y++){
for (int z = zstart; z < zend; z++){
yield(std::make_tuple(x, y, z));
}
}
}
});
for(auto p : points)
function_doing_stuff(p);
Since you care about performance, you should forget about combining iterators for the foreseeable future. The central problem is that compilers cannot yet untangle the mess and figure out that there are 3 independent variables in it, much less perform any loop interchange or unrolling or fusion.
If you must use ranges, use simple ones that the compiler can see through:
for (int const x : boost::irange<int>(xstart,xend))
for (int const y : boost::irange<int>(ystart,yend))
for (int const z : boost::irange<int>(zstart,zend))
function_doing_stuff(x, y, z);
Alternatively, you can actually pass your functor and the boost ranges to a template:
template <typename Func, typename Range0, typename Range1, typename Range2>
void apply_ranges (Func func, Range0 r0, Range1 r1, Range2 r2)
{
for (auto const i0 : r0)
for (auto const i1 : r1)
for (auto const i2 : r2)
func (i0, i1, i2);
}
If you truly care about performance, then you should not contort your code with complicated ranges, because they make it harder to untangle later when you want to rewrite them in AVX intrinsics.
Here's a bare-bones implementation that does not use any advanced language features or other libraries. The performance should be pretty close to the for loop version.
#include <tuple>
class MyRange {
public:
typedef std::tuple<int, int, int> valtype;
MyRange(int xstart, int xend, int ystart, int yend, int zstart, int zend): xstart(xstart), xend(xend), ystart(ystart), yend(yend), zstart(zstart), zend(zend) {
}
class iterator {
public:
iterator(MyRange &c): me(c) {
curvalue = std::make_tuple(me.xstart, me.ystart, me.zstart);
}
iterator(MyRange &c, bool end): me(c) {
curvalue = std::make_tuple(end ? me.xend : me.xstart, me.ystart, me.zstart);
}
valtype operator*() {
return curvalue;
}
iterator &operator++() {
if (++std::get<2>(curvalue) == me.zend) {
std::get<2>(curvalue) = me.zstart;
if (++std::get<1>(curvalue) == me.yend) {
std::get<1>(curvalue) = me.ystart;
++std::get<0>(curvalue);
}
}
return *this;
}
bool operator==(const iterator &other) const {
return curvalue == other.curvalue;
}
bool operator!=(const iterator &other) const {
return curvalue != other.curvalue;
}
private:
MyRange &me;
valtype curvalue;
};
iterator begin() {
return iterator(*this);
}
iterator end() {
return iterator(*this, true);
}
private:
int xstart, xend;
int ystart, yend;
int zstart, zend;
};
And an example of usage:
#include <iostream>
void display(std::tuple<int, int, int> v) {
std::cout << "(" << std::get<0>(v) << ", " << std::get<1>(v) << ", " << std::get<2>(v) << ")\n";
}
int main() {
MyRange c(1, 4, 2, 5, 7, 9);
for (auto v: c) {
display(v);
}
}
I've left off things like const iterators, possible operator+=, decrementing, post increment, etc. They've been left as an exercise for the reader.
It stores the initial values, then increments each value in turn, rolling it back and incrementing the next when it get to the end value. It's a bit like incrementing a multi-digit number.
Using boost::iterator_facade for simplicity, you can spell out all the required members.
First we have a class that iterates N-dimensional indexes as std::array<std::size_t, N>
template<std::size_t N>
class indexes_iterator : public boost::iterator_facade<indexes_iterator, std::array<std::size_t, N>>
{
public:
template<typename... Dims>
indexes_iterator(Dims... dims) : dims{ dims... }, values{} {}
private:
friend class boost::iterator_core_access;
void increment() { advance(1); }
void decrement() { advance(-1); }
void advance(int n)
{
for (std::size_t i = 0; i < N; ++i)
{
int next = ((values[i] + n) % dims[i]);
n = (n \ dims[i]) + (next < value);
values[i] = next;
}
}
std::size_t distance(indexes_iterator const & other) const
{
std::size_t result = 0, mul = 1;
for (std::size_t i = 0; i < dims; ++i)
{
result += mul * other[i] - values[i];
mul *= ends[i];
}
}
bool equal(indexes_iterator const& other) const
{
return values == other.values;
}
std::array<std::size_t, N> & dereference() const { return values; }
std::array<std::size_t, N> ends;
std::array<std::size_t, N> values;
}
Then we use that to make something similar to a boost::zip_iterator, but instead of advancing all together we add our indexes.
template <typename... Iterators>
class product_iterator : public boost::iterator_facade<product_iterator<Iterators...>, const std::tuple<decltype(*std::declval<Iterators>())...>, boost::random_access_traversal_tag>
{
using ref = std::tuple<decltype(*std::declval<Iterators>())...>;
public:
product_iterator(Iterators ... ends) : indexes() , iterators(std::make_tuple(ends...)) {}
template <typename ... Sizes>
product_iterator(Iterators ... begins, Sizes ... sizes)
: indexes(sizes...),
iterators(begins...)
{}
private:
friend class boost::iterator_core_access;
template<std::size_t... Is>
ref dereference_impl(std::index_sequence<Is...> idxs) const
{
auto offs = offset(idxs);
return { *std::get<Is>(offs)... };
}
ref dereference() const
{
return dereference_impl(std::index_sequence_for<Iterators...>{});
}
void increment() { ++indexes; }
void decrement() { --indexes; }
void advance(int n) { indexes += n; }
template<std::size_t... Is>
std::tuple<Iterators...> offset(std::index_sequence<Is...>) const
{
auto idxs = *indexes;
return { (std::get<Is>(iterators) + std::get<Is>(idxs))... };
}
bool equal(product_iterator const & other) const
{
return offset(std::index_sequence_for<Iterators...>{})
== other.offset(std::index_sequence_for<Iterators...>{});
}
indexes_iterator<sizeof...(Iterators)> indexes;
std::tuple<Iterators...> iterators;
};
Then we wrap it up in a boost::iterator_range
template <typename... Ranges>
auto make_product_range(Ranges&&... rngs)
{
product_iterator<decltype(begin(rngs))...> b(begin(rngs)..., std::distance(std::begin(rngs), std::end(rngs))...);
product_iterator<decltype(begin(rngs))...> e(end(rngs)...);
return boost::iterator_range<product_iterator<decltype(begin(rngs))...>>(b, e);
}
int main()
{
using ranges::view::iota;
for (auto p : make_product_range(iota(xstart, xend), iota(ystart, yend), iota(zstart, zend)))
// ...
return 0;
}
See it on godbolt
Just a very simplified version that will be as efficient as a for loop:
#include <tuple>
struct iterator{
int x;
int x_start;
int x_end;
int y;
int y_start;
int y_end;
int z;
constexpr auto
operator*() const{
return std::tuple{x,y,z};
}
constexpr iterator&
operator++ [[gnu::always_inline]](){
++x;
if (x==x_end){
x=x_start;
++y;
if (y==y_end) {
++z;
y=y_start;
}
}
return *this;
}
constexpr iterator
operator++(int){
auto old=*this;
operator++();
return old;
}
};
struct sentinel{
int z_end;
friend constexpr bool
operator == (const iterator& x,const sentinel& s){
return x.z==s.z_end;
}
friend constexpr bool
operator == (const sentinel& a,const iterator& x){
return x==a;
}
friend constexpr bool
operator != (const iterator& x,const sentinel& a){
return !(x==a);
}
friend constexpr bool
operator != (const sentinel& a,const iterator& x){
return !(x==a);
}
};
struct range{
iterator start;
sentinel finish;
constexpr auto
begin() const{
return start;
}
constexpr auto
end()const{
return finish;
}
};
void func(int,int,int);
void test(const range& r){
for(auto [x,y,z]: r)
func(x,y,z);
}
void test(int x_start,int x_end,int y_start,int y_end,int z_start,int z_end){
for(int z=z_start;z<z_end;++z)
for(int y=y_start;y<y_end;++y)
for(int x=x_start;x<x_end;++x)
func(x,y,z);
}
The advantage over 1201ProgramAlarm answer is the faster test performed at each iteration thanks to the use of a sentinel.
i have to filter a container and the copy of each item is expensive. So i came up with this C++ code .. maybe there is better concept that i miss. Please comment. Also important that operations like counting and empty are also fast.
The sample below will create a vector with some items and return a filtered copy and doing some boolean operations.
#include <vector>
#include <functional>
template <class X> struct filterChainT {
/// the list here
const X & list;
/// take store type from access operator
typedef decltype(list[0]) storeType;
/// the test functions
std::function<bool(storeType &) > tests[10];
/// counting the test (don´t use array here)
size_t countTest;
/// ctor with given list
filterChainT(const X & list):list(list),countTest(0) { }
/// add a rule here
filterChainT<X> & apply(const std::function<bool(storeType &) > & fnc)
{
tests[countTest++] = fnc;
return *this;
}
/// downcast to container (will return the filter copy)
operator X() const
{
X ret;
eval([&](const storeType & hit) { ret.push_back(hit); return false; });
return ret;
}
/// just count item after filter
int count() const
{
int count = 0;
eval([&](const storeType hit) { count++; return false; });
return count;
}
bool operator==(int number) const { return count() == number; }
bool operator>(int number) const
{
int count = 0;
return eval([&](const storeType & hit) { return ++count>number; });
}
bool operator<(int number) const
{
int count = 0;
return !eval([&](const storeType & hit) { return ++count>=number; });
}
//// the magic eval functions. Return true if the fnc object abort the loop
template <class FNC> bool eval(const FNC fnc) const
{
for (auto i : list)
{
for (size_t t = 0; t < countTest; t++)
{
if (!tests[t](i))
goto next;
}
if (fnc(i))
return true;
next:;
}
return false;
}
};
struct myFilter : public filterChainT < std::vector<int>> {
myFilter(const std::vector<int> & in) :filterChainT<std::vector<int>>(in){ };
// filter items i%2==0
myFilter & mod()
{
apply([](const int & i) { return i % 2; });
return *this;
}
// filter items smaller than x
myFilter & smaller(int x)
{
apply([=](const int & i) { return i<x; });
return *this;
}
};
int main()
{
std::vector<int> vec;
vec.push_back(1);
vec.push_back(3);
vec.push_back(10);
// apply filter and return result use two filters „mod“ and „smaller“
std::vector<int> ret = myFilter(vec).mod().smaller(5);
// just see if they are less then 2 items in list same filter than above
bool res1 = myFilter(vec).mod().smaller(5) < 2;
// some custom without the helper -> filter all items larger than 3 and put in list
std::vector<int> result=filterChainT < std::vector<int>>(vec).apply([](const int & p) { return p > 3; });
}
regards
Markus
the hint with "expression templates" works very well. Two times faster than my posting. Now the code looks like this. Thank you very much for pointing to the right place.
I use the same concept as the WIKI entry by adding a plus operation to create the filter chain and a final function to reduce the given list with this filter.
template <class T> struct filterNodeBaseT {
template <class X> bool apply(const X& x) const { return static_cast<T const & >(*this).apply(x); }
template <class LST> LST filter(const LST & input) const
{ LST ret;
for (auto i : input)
{ if (this->apply(i))
ret.push_back(i);
}
return ret;
}
template <class LST> int count(const LST & input) const
{ int ret = 0;
for (auto i : input)
{ if (this->apply(i))
ret++;
}
return ret;
}
};
template <class T1, class T2> struct filterCombine : public filterNodeBaseT<filterCombine<T1, T2> > {
const T1 & t1;
const T2 & t2;
filterCombine(const T1 & t1, const T2 & t2) :t1(t1), t2(t2) { }
template <class X> bool apply(const X & x) const { return t1.apply(x) && t2.apply(x); }
};
template <class T1,class T2> filterCombine<T1,T2> operator + (const T1 & t1,const T2 & t2)
{ return filterCombine<T1,T2>(t1,t2); }
struct filterNodeSmaller : public filterNodeBaseT<filterNodeSmaller> {
int limit;
filterNodeSmaller(int limit) :limit(limit) {};
bool apply(const int & x) const { return x < limit; }
};
struct filterNodeLarger: public filterNodeBaseT<filterNodeLarger> {
int limit;
filterNodeLarger(int limit) :limit(limit) {};
bool apply(const int & x) const { return x > limit; }
};
struct filterNodeMod : public filterNodeBaseT<filterNodeMod> {
bool apply(const int & x) const { return x % 2; }
};
struct filterStrlenLarger : public filterNodeBaseT<filterStrlenLarger> {
int limit;
filterStrlenLarger(int limit) :limit(limit) { };
bool apply(const std::string & s) const { return s.length() > limit; }
};
struct filterStrGreater : public filterNodeBaseT<filterStrGreater> {
std::string cmp;
filterStrGreater(const std::string & cmp) :cmp(cmp) { };
bool apply(const std::string & s) const { return s>cmp; }
};
_declspec(noinline) void nodeTest()
{
std::vector<int> intList;
intList.push_back(1); intList.push_back(3); intList.push_back(4);
int count= (filterNodeMod() + filterNodeSmaller(5)+ filterNodeLarger(1)).count(intList);
std::vector<int> resList1= (filterNodeMod() + filterNodeSmaller(5)+filterNodeLarger(1)).filter(intList);
printf("%d\n", count);
std::vector<std::string> strList;
strList.push_back("Hello");
strList.push_back("World");
strList.push_back("!");
count = (filterStrlenLarger(3)+filterStrGreater("Hello")).count(strList);
std::vector<std::string> resList2= (filterStrlenLarger(3) + filterStrGreater("Hello")).filter(strList);
printf("%d\n", count);
}
template< typename T >
double GetAverage(T tArray[], int nElements)
{
T tSum = T(); // tSum = 0
for (int nIndex = 0; nIndex < nElements; ++nIndex)
{
tSum += tArray[nIndex];
}
// convert T to double
return double(tSum) / nElements;
};
template <typename T>
class pair {
public:
T a;
T b;
pair () {
a=T(0);
b=T(0);
} ;
pair (T a1, T b1) {
a=a1;
b=b1;
};
pair operator += (pair other_pair) {
return pair(a+other_pair.a, b+other_pair.b);
}
operator double() {
return double(a)+ double(b);
}
};
int main(void)
{
pair<int > p1[1];
p1[0]=pair<int >(3,4);
std::cout<< GetAverage <pair <int >>(p1,1) <<"\n";
}
I can't understand why it prints 0 instead of 3.5.
When I copy code from C++ -- How to overload operator+=? all went fine. But I can't understand where I have made
a mistake
pair operator += (pair other_pair) {
return pair(a+other_pair.a, b+other_pair.b);
}
should be
pair &operator += (const pair &other_pair) {
a += other_pair.a;
b += other_pair.b;
return *this;
}
You need to modify the members of this and return a reference to *this, instead of a new object.
It is also a good idea to pass other_pair as a const reference instead of by value.
Is it possible to have a generic constructor that takes any type of initializer list, even if this has nested lists within?
Say you have the following partial template specialization for a class that takes in its constructor nested initializer lists:
template
class ClassA;
template <>
class ClassA<4> {
typedef std::initializer_list<double> list_type;
typedef std::initializer_list<list_type> llist_type;
typedef std::initializer_list<llist_type> lllist_type;
typedef std::initializer_list<lllist_type> initializer_type;
size_t n_[4] = {0};
double* data_;
public:
ClassA(initializer_type l) {
assert(l.size() > 0);
assert(l.begin()->size() > 0);
assert(l.begin()->begin()->size() > 0);
assert(l.begin()->begin()->begin()->size() > 0);
size_t m = n_[0] = l.size();
size_t n = n_[1] = l.begin()->size();
size_t o = n_[2] = l.begin()->begin()->size();
n_[3] = l.begin()->begin()->begin()->size();
data_ = new double[m*n*o*n_[3]];
int i=0, j=0, k=0, p=0;
for (const auto& u : l) {
assert(u.size() == n_[1]);
for (const auto& v : u) {
assert(v.size() == n_[2]);
for (const auto& x : v) {
assert(x.size() == n_[3]);
for (const auto& y : x) {
data_[i + m*j + m*n*k + m*n*o*p] = y;
++p;
}
p = 0;
++k;
}
k = 0;
++j;
}
j = 0;
++i;
}
}
size_t size() const {
size_t n = 1;
for (size_t i=0; i<4; ++i)
n *= n_[i];
return n;
}
friend std::ostream& operator<<(std::ostream& os, const ClassA& a) {
for (int i=0; i<a.size(); ++i)
os<<" "<<a.data_[i];
return os<<endl;
}
};
int main()
{
ClassA<4> TT = { {{{1.}, {7.}, {13.}, {19}}, {{2}, {8}, {14}, {20}}, {{3}, {9}, {15}, {21}}}, {{{4.}, {10}, {16}, {22}}, {{5}, {11}, {17}, {23}}, {{6}, {12}, {18}, {24}}} };
cout<<"TT -> "<<TT<<endl;
return 0;
}
This code prints:
TT -> 1 4 2 5 3 6 7 10 8 11 9 12 13 16 14 17 15 18 19 22 20 23 21 24
Now, I'm trying to generalize the constructor so that I don't have to specialize the class template for each dimension.
The problem is that when I replace the constructor with something like:
template <class L>
ClassA(std::initializer_list<L> l) {
cout<<"generic list constructor"<<endl;
}
The clang compiler fails with error:
error: no matching constructor for initialization of 'ClassA<4>
Can someone point out why is this happening? The template matching is not working for initializer lists, probably because this is a new C++ feature?
Thank you all...
EDIT
Thanks to the help of #JohannesSchaub-litb and #Daniel Frey, I was able to craft a very generic constructor that takes the initializer_list of any dimension. This is the resulting code:
template <int d, typename T>
class ClassA {
size_t n_[d] = {0};
T* data_;
template <int D, typename U>
struct Initializer_list {
typedef std::initializer_list<typename Initializer_list<D-1,U>::list_type > list_type;
Initializer_list(list_type l, ClassA& a, size_t s, size_t idx) {
a.n_[d-D] = l.size();
size_t j = 0;
for (const auto& r : l)
Initializer_list<D-1, U> pl(r, a, s*l.size(), idx + s*j++);
}
};
template <typename U>
struct Initializer_list<1,U> {
typedef std::initializer_list<T> list_type;
Initializer_list(list_type l, ClassA& a, size_t s, size_t i) {
a.n_[d-1] = l.size();
if (!a.data_)
a.data_ = new T[s*l.size()];
size_t j = 0;
for (const auto& r : l)
a.data_[i + s*j++] = r;
}
};
typedef typename Initializer_list<d,T>::list_type initializer_type;
public:
// initializer list constructor
ClassA(initializer_type l) : data_(nullptr) {
Initializer_list<d, T> r(l, *this, 1, 0);
}
size_t size() const {
size_t n = 1;
for (size_t i=0; i<4; ++i)
n *= n_[i];
return n;
}
friend std::ostream& operator<<(std::ostream& os, const ClassA& a) {
for (int i=0; i<a.size(); ++i)
os<<" "<<a.data_[i];
return os<<endl;
}
};
int main()
{
ClassA<4, double> TT = { {{{1.}, {7.}, {13.}, {19}}, {{2}, {8}, {14}, {20}}, {{3}, {9}, {15}, {21}}}, {{{4.}, {10}, {16}, {22}}, {{5}, {11}, {17}, {23}}, {{6}, {12}, {18}, {24}}} };
cout<<"TT -> "<<TT<<endl;
return 0;
}
Of course the code prints
TT -> 1 4 2 5 3 6 7 10 8 11 9 12 13 16 14 17 15 18 19 22 20 23 21 24
I love this template metaprogramming stuff!
Thank you guys for helping figuring this out.
aa
I believe what you really want to do is to automatically build the right type
template<int S, typename E>
class make_list_type {
public:
typedef std::initializer_list<
typename make_list_type<S-1, E>::type
> type;
};
template<typename E>
class make_list_type<0, E> {
public:
typedef E type;
};
template<int S>
class ClassA {
typedef typename make_list_type<S, double>::type initializer_type;
public:
ClassA(initializer_type l)
};
As for why your try did not work, see Templates don't always guess initializer list types
In general, the answer is (AFAIK): No. But for your specific case, you might use the knowledge that it all ends with double as the leafs:
class arg_type
{
private:
bool is_value;
double d;
std::vector<arg_type> subs;
public:
arg_type(double v) : is_value(true), d(v) {}
arg_type(std::initializer_list<arg_type> l) : is_value(false), subs(l) {}
};
and change your ctor to:
typedef std::initializer_list<arg_type> initializer_type;
ClassA(initializer_type l) {
// ...
}
Hope it helps...
Update: As pointed out by Mankarse (thanks!), the above has undefined behaviour. Here's a version that should fix it without using Boost:
#include <vector>
#include <memory>
#include <iostream>
#include <initializer_list>
class arg_type
{
private:
std::shared_ptr<void> subs; // empty => d is valid
double d;
public:
arg_type(double v) : d(v) {}
arg_type(std::initializer_list<arg_type> l);
void print() const;
};
arg_type::arg_type(std::initializer_list<arg_type> l)
: subs(std::make_shared<std::vector<arg_type>>(l))
{}
void arg_type::print() const
{
if( subs ) {
std::cout << "( ";
for( const auto& e : *std::static_pointer_cast<std::vector<arg_type>>(subs) ) {
e.print();
}
std::cout << ") ";
}
else {
std::cout << d << " ";
}
}
struct MyClass
{
MyClass( std::initializer_list<arg_type> l) {
for( const auto& e : l ){
e.print();
}
}
};
int main()
{
MyClass m { 1, 2, { 3, 4, { 6, 7, { 8 }}}, 5 };
}
If you want to play with it, here's the live example.