std::bind requires default constructor - c++

Im working on a project to school(as namespace name may hint, it is 2D game) and Ive made a custom class called RangeInt(Range) which just wraps two variables of same type and made another class called Randomizer which wraps the C++11 standard random number generation and uses the RangeInt class to specify the range I want to generate the numbers.
Well anyways here is the code:
namespace game{
template<class _Type>
//very simple class representing virtual Range
//of type _Type(template argument) and storing
//upper and lower bound
class Range{
public:
typedef _Type TemplateParam;
//value sto use of type _Type
_Type first, second;
//copy constructor:
Range(const Range& rng)
{
first = rng.first;
second = rng.second;
}
//move construct:
Range(Range&& rng)
{
std::swap(*this, rng);
}
Range& operator=(const Range& range)
{
first = range.first;
second = range.second;
return *this;
}
Range& operator=(Range&& range)
{
std::swap(first, range.first);
std::swap(second, range.second);
return *this;
}
//constructor
Range(_Type one, _Type two) : first(one), second(two) {}
//returns two - one
inline _Type getDifference() { return two - one; }
};
typedef Range<uint> RangeInt;
};
and the randomizer:
namespace game{
template <class _RNG = xorshift>
class Randomizer_RNG{
typedef _RNG random_generator;
RangeInt rng;
random_generator mt;
std::uniform_int_distribution<> dist;
//reinitialize the dist variable so it actually knows the new range
void _changeDist()
{
dist = std::uniform_int_distribution<>(rng.first, rng.second);
}
public:
//default constructor, set rng to maximum range and initialize
//the xorshift with seed being current time and specify the
//range for uniform_int_distribution
Randomizer_RNG()
{
rng = game::RangeInt(0, std::numeric_limits<game::uint>::max());
dist = std::uniform_int_distribution<>(range.first, range.second);
mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
}
//do the same as constructor above but with specified range
explicit Randomizer_RNG(RangeInt range) : rng(range)
{
dist = std::uniform_int_distribution<>(rng.first, rng.second);
mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
}
//copy constructor
Randomizer_RNG(const Randomizer_RNG& lhs)
{
dist = lhs.dist;
mt = lhs.mt;
rng = lhs.rng;
}
//move constructor
Randomizer_RNG(Randomizer_RNG&& lhs)
{
std::swap(*this, lhs);
}
//reseed with current time
inline void seed()
{
mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
}
//reseed with specified value
inline void seed(unsigned long long newSeed)
{
mt.seed(newSeed);
}
//default operator()
uint32 operator()()
{
return dist(mt);
}
//return value generated in range of
//<fitWithin.first, fitWithin.second>
uint32 operator()(RangeInt&& fitWithin)
{
decltype(dist) l_dist(fitWithin.first, fitWithin.second);
return l_dist(mt);
}
//the same as above, but with rvalue reference
uint32 operator()(RangeInt& fitWithin)
{
decltype(dist) l_dist(fitWithin.first, fitWithin.second);
return l_dist(mt);
}
//change range with reference
void changeRange(const RangeInt& rng)
{
this->rng = rng;
_changeDist();
}
//the same as above but with rvalue reference
void changeRange(RangeInt&& rng)
{
std::swap(this->rng, rng);
_changeDist();
}
//set the upper bound of the range and update rng
void setUpperBound(RangeInt::TemplateParam upBound)
{
rng.second = upBound;
_changeDist();
}
//set the lower bound of the range and update rng
void setLowerBound(RangeInt::TemplateParam lowBound)
{
rng.first = lowBound;
_changeDist();
}
//copy assignment
Randomizer_RNG& operator=(const Randomizer_RNG& lhs)
{
_RETURN_IF_THIS(lhs, *this); //if (*this == lhs) return *this;
rng = lhs.rng;
changeRange(rng);
return *this;
}
//move assignment
Randomizer_RNG& operator=(Randomizer_RNG&& lhs)
{
dist = std::move(lhs.dist);
rng = std::move(lhs.rng);
mt = std::move(lhs.mt);
return *this;
}
};
typedef Randomizer_RNG<> Randomizer;
typedef Randomizer_RNG<std::mt19937> Randomizer_Twist;
};
but when I do
#include "randomizer.h"
int main()
{
game::RangeInt rngI (14, 546);
game::Randomizer rng = game::Randomizer(game::RangeInt(0, 100));
auto func = std::bind(rng, rngI);
std::cout << func();
std::cin.get();
}
it pops compiler error:
error C2512: 'game::Range<_Type>' : no appropriate default constructor available
with
[
_Type=game::uint
]
And if I try to do:
#include "randomizer.h"
int main()
{
game::RangeInt rngI (14, 546);
game::Randomizer rng = game::Randomizer(game::RangeInt(0, 100));
auto func = std::bind(&rng, rngI);
std::cout << func();
std::cin.get();
}
it says:
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'std::_Do_call_ret<_Forced,_Ret,_Funx,_Btuple,_Ftuple>::type' (or there is no acceptable conversion)
So I wonder if Im doing something wrong or why does std::bind want default constructor from me for game::Range.
If my question is not clear or the code is not clear, let me know I will do my best.
PS: Im using Visual Studio 2012 so Variadic templates are not implemented(std::bind for instance has 378 overlaods)

Make it
Randomizer_RNG(const Randomizer_RNG& lhs)
: dist(lhs.dist), mt(lhs.mt), rng(lhs.rng)
{}
or just drop this constructor altogether: the compiler-generated one is good enough.
As written, your constructor tries to default-construct rng first, and then assign to it. But, as the compiler tells you, Range doesn't provide a default constructor.

Related

Get byte representation of C++ class

I have objects that I need to hash with SHA256. The object has several fields as follows:
class Foo {
// some methods
protected:
std::array<32,int> x;
char y[32];
long z;
}
Is there a way I can directly access the bytes representing the 3 member variables in memory as I would a struct ? These hashes need to be computed as quickly as possible so I want to avoid malloc'ing a new set of bytes and copying to a heap allocated array. Or is the answer to simply embed a struct within the class?
It is critical that I get the exact binary representation of these variables so that the SHA256 comes out exactly the same given that the 3 variables are equal (so I can't have any extra padding bytes etc included going into the hash function)
Most Hash classes are able to take multiple regions before returning the hash, e.g. as in:
class Hash {
public:
void update(const void *data, size_t size) = 0;
std::vector<uint8_t> digest() = 0;
}
So your hash method could look like this:
std::vector<uint8_t> Foo::hash(Hash *hash) const {
hash->update(&x, sizeof(x));
hash->update(&y, sizeof(y));
hash->update(&z, sizeof(z));
return hash->digest();
}
You can solve this by making an iterator that knows the layout of your member variables. Make Foo::begin() and Foo::end() functions and you can even take advantage of range-based for loops.
If you can increment it and dereference it, you can use it any other place you're able to use a LegacyForwardIterator.
Add in comparison functions to get access to the common it = X.begin(); it != X.end(); ++it idiom.
Some downsides include: ugly library code, poor maintainability, and (in this current form) no regard for endianess.
The solution to the latter downside is left as an exercise to the reader.
#include <array>
#include <iostream>
class Foo {
friend class FooByteIter;
public:
FooByteIter begin() const;
FooByteIter end() const;
Foo(const std::array<int, 2>& x, const char (&y)[2], long z)
: x_{x}
, y_{y[0], y[1]}
, z_{z}
{}
protected:
std::array<int, 2> x_;
char y_[2];
long z_;
};
class FooByteIter {
public:
FooByteIter(const Foo& foo)
: ptr_{reinterpret_cast<const char*>(&(foo.x_))}
, x_end_{reinterpret_cast<const char*>(&(foo.x_)) + sizeof(foo.x_)}
, y_begin_{reinterpret_cast<const char*>(&(foo.y_))}
, y_end_{reinterpret_cast<const char*>(&(foo.y_)) + sizeof(foo.y_)}
, z_begin_{reinterpret_cast<const char*>(&(foo.z_))}
{}
static FooByteIter end(const Foo& foo) {
FooByteIter fbi{foo};
fbi.ptr_ = reinterpret_cast<const char*>(&foo.z_) + sizeof(foo.z_);
return fbi;
}
bool operator==(const FooByteIter& other) const { return ptr_ == other.ptr_; }
bool operator!=(const FooByteIter& other) const { return ! (*this == other); }
FooByteIter& operator++() {
ptr_++;
if (ptr_ == x_end_) {
ptr_ = y_begin_;
}
else if (ptr_ == y_end_) {
ptr_ = z_begin_;
}
return *this;
}
FooByteIter operator++(int) {
FooByteIter pre = *this;
(*this)++;
return pre;
}
char operator*() const {
return *ptr_;
}
private:
const char* ptr_;
const char* const x_end_;
const char* const y_begin_;
const char* const y_end_;
const char* const z_begin_;
};
FooByteIter Foo::begin() const {
return FooByteIter(*this);
}
FooByteIter Foo::end() const {
return FooByteIter::end(*this);
}
template <typename InputIt>
char checksum(InputIt first, InputIt last) {
char check = 0;
while (first != last) {
check += (*first);
++first;
}
return check;
}
int main() {
Foo f{{1, 2}, {3, 4}, 5};
for (const auto b : f) {
std::cout << (int)b << ' ';
}
std::cout << std::endl;
std::cout << "Checksum is: " << (int)checksum(f.begin(), f.end()) << std::endl;
}
You can generalize this further by making serialization functions for all data types you might care about, allowing serialization of classes that aren't plain-old-data types.
Warning
This code assumes that the underlying types being serialized have no internal padding, themselves. This answer works for this datatype because it is made of types which themselves do not pad. To make this work for datatypes that have datatypes that have padding, this method would need to be recursed all the way down.
Just cast a pointer to object to a pointer to char. You can iterate through the bytes by increment. Use sizeof(foo) to check overflow.
As long as you're able to make your class an aggregate, i.e. std::is_aggregate_v<T> == true, you can actually sort-of reflect the members of the structure.
This allows you to easily hash the members without actually having to name them. (also you don't have to remember updating your hash function every time you add a new member)
Step 1: Getting the number of members inside the aggregate
First we need to know how many members a given aggregate type has.
We can check this by (ab-)using aggregate initialization.
Example:
Given struct Foo { int i; int j; };:
Foo a{}; // ok
Foo b{{}}; // ok
Foo c{{}, {}}; // ok
Foo d{{}, {}, {}}; // error: too many initializers for 'Foo'
We can use this to get the number of members inside the struct, by trying to add more initializers until we get an error:
template<class T>
concept aggregate = std::is_aggregate_v<T>;
struct any_type {
template<class T>
operator T() {}
};
template<aggregate T>
consteval std::size_t count_members(auto ...members) {
if constexpr (requires { T{ {members}... }; } == false)
return sizeof...(members) - 1;
else
return count_members<T>(members..., any_type{});
}
Notice that i used {members}... instead of members....
This is because of arrays - a structure like struct Bar{int i[2];}; could be initialized with 2 elements, e.g. Bar b{1, 2}, so our function would have returned 2 for Bar if we had used members....
Step 2: Extracting the members
Now that we know how many members our structure has, we can use structured bindings to extract them.
Unfortunately there is no way in the current standard to create a structured binding expression with a variable amount of expressions, so we have to add a few extra lines of code for each additional member we want to support.
For this example i've only added a max of 4 members, but you can add as many as you like / need:
template<aggregate T>
constexpr auto tie_struct(T const& data) {
constexpr std::size_t fieldCount = count_members<T>();
if constexpr(fieldCount == 0) {
return std::tie();
} else if constexpr (fieldCount == 1) {
auto const& [m1] = data;
return std::tie(m1);
} else if constexpr (fieldCount == 2) {
auto const& [m1, m2] = data;
return std::tie(m1, m2);
} else if constexpr (fieldCount == 3) {
auto const& [m1, m2, m3] = data;
return std::tie(m1, m2, m3);
} else if constexpr (fieldCount == 4) {
auto const& [m1, m2, m3, m4] = data;
return std::tie(m1, m2, m3, m4);
} else {
static_assert(fieldCount!=fieldCount, "Too many fields for tie_struct! add more if statements!");
}
}
The fieldCount!=fieldCount in the static_assert is intentional, this prevents the compiler from evaluating it prematurely (it only complains if the else case is actually hit)
Now we have a function that can give us references to each member of an arbitrary aggregate.
Example:
struct Foo {int i; float j; std::string s; };
Foo f{1, 2, "miau"};
// tup is of type std::tuple<int const&, float const&, std::string const&>
auto tup = tie_struct(f);
// this will output "12miau"
std::cout << std::get<0>(tup) << std::get<1>(tup) << std::get<2>(tup) << std::endl;
Step 3: hashing the members
Now that we can convert any aggregate into a tuple of its members, hashing it shouldn't be a big problem.
You can basically hash the individual types like you want and then combine the individual hashes:
// for merging two hash values
std::size_t hash_combine(std::size_t h1, std::size_t h2)
{
return (h2 + 0x9e3779b9 + (h1<<6) + (h1>>2)) ^ h1;
}
// Handling primitives
template <class T, class = void>
struct is_std_hashable : std::false_type { };
template <class T>
struct is_std_hashable<T, std::void_t<decltype(std::declval<std::hash<T>>()(std::declval<T>()))>> : std::true_type { };
template <class T>
concept std_hashable = is_std_hashable<T>::value;
template<std_hashable T>
std::size_t hash(T value) {
return std::hash<T>{}(value);
}
// Handling tuples
template<class... Members>
std::size_t hash(std::tuple<Members...> const& tuple) {
return std::apply([](auto const&... members) {
std::size_t result = 0;
((result = hash_combine(result, hash(members))), ...);
return result;
}, tuple);
}
template<class T, std::size_t I>
using Arr = T[I];
// Handling arrays
template<class T, std::size_t I>
std::size_t hash(Arr<T, I> const& arr) {
std::size_t result = 0;
for(T const& elem : arr) {
std::size_t h = hash(elem);
result = hash_combine(result, h);
}
return result;
};
// Handling structs
template<aggregate T>
std::size_t hash(T const& agg) {
return hash(tie_struct(agg));
}
This allows you to hash basically any aggregate struct, even with arrays and nested structs:
struct Foo{ int i; double d; std::string s; };
struct Bar { Foo k[10]; float f; };
std::cout << hash(Foo{1, 1.2f, "miau"}) << std::endl;
std::cout << hash(Bar{}) << std::endl;
full example on godbolt
Footnotes
This only works with aggregates
No need to worry about padding because we access the members directly.
You have to add a few more ifs into tie_struct if you need more than 4 members
The provided hash() function doesn't handle all types - if you need e.g. std::array, std::pair, etc... you need to add overloads for those.
It's a lot of boilerplate code, but it's insanely powerful.
You can also use Boost.PFR for the aggregate-to-tuple part, if you are allowed to use boost

How to make a for loop variable const with the exception of the increment statement?

Consider a standard for loop:
for (int i = 0; i < 10; ++i)
{
// do something with i
}
I want to prevent the variable i from being modified in the body of the for loop.
However, I cannot declare i as const as this makes the increment statement invalid. Is there a way to make i a const variable outside of the increment statement?
From c++20, you can use ranges::views::iota like this:
for (int const i : std::views::iota(0, 10))
{
std::cout << i << " "; // ok
i = 42; // error
}
Here's a demo.
From c++11, you can also use the following technique, which uses an IIILE (immediately invoked inline lambda expression):
int x = 0;
for (int i = 0; i < 10; ++i) [&,i] {
std::cout << i << " "; // ok, i is readable
i = 42; // error, i is captured by non-mutable copy
x++; // ok, x is captured by mutable reference
}(); // IIILE
Here's a demo.
Note that [&,i] means that i is captured by non-mutable copy, and everything else is captured by mutable reference. The (); at the end of the loop simply means that the lambda is invoked immediately.
For anyone that likes Cigien's std::views::iota answer but isn't working in C++20 or above, it's rather straightforward to implement a simplified and lightweight version of std::views::iota compatible c++11 or above.
All it requires is:
A basic "LegacyInputIterator" type (something that defines operator++ and operator*) that wraps an integral value (e.g. an int)
Some "range"-like class that has begin() and end() that returns the above iterators. This will allow it to work in range-based for loops
A simplified version of this could be:
#include <iterator>
// This is just a class that wraps an 'int' in an iterator abstraction
// Comparisons compare the underlying value, and 'operator++' just
// increments the underlying int
class counting_iterator
{
public:
// basic iterator boilerplate
using iterator_category = std::input_iterator_tag;
using value_type = int;
using reference = int;
using pointer = int*;
using difference_type = std::ptrdiff_t;
// Constructor / assignment
constexpr explicit counting_iterator(int x) : m_value{x}{}
constexpr counting_iterator(const counting_iterator&) = default;
constexpr counting_iterator& operator=(const counting_iterator&) = default;
// "Dereference" (just returns the underlying value)
constexpr reference operator*() const { return m_value; }
constexpr pointer operator->() const { return &m_value; }
// Advancing iterator (just increments the value)
constexpr counting_iterator& operator++() {
m_value++;
return (*this);
}
constexpr counting_iterator operator++(int) {
const auto copy = (*this);
++(*this);
return copy;
}
// Comparison
constexpr bool operator==(const counting_iterator& other) const noexcept {
return m_value == other.m_value;
}
constexpr bool operator!=(const counting_iterator& other) const noexcept {
return m_value != other.m_value;
}
private:
int m_value;
};
// Just a holder type that defines 'begin' and 'end' for
// range-based iteration. This holds the first and last element
// (start and end of the range)
// The begin iterator is made from the first value, and the
// end iterator is made from the second value.
struct iota_range
{
int first;
int last;
constexpr counting_iterator begin() const { return counting_iterator{first}; }
constexpr counting_iterator end() const { return counting_iterator{last}; }
};
// A simple helper function to return the range
// This function isn't strictly necessary, you could just construct
// the 'iota_range' directly
constexpr iota_range iota(int first, int last)
{
return iota_range{first, last};
}
I've defined the above with constexpr where it's supported, but for earlier versions of C++ like C++11/14, you may need to remove constexpr where it is not legal in those versions to do so.
The above boilerplate enables the following code to work in pre-C++20:
for (int const i : iota(0, 10))
{
std::cout << i << " "; // ok
i = 42; // error
}
Which will generate the same assembly as the C++20 std::views::iota solution and the classic for-loop solution when optimized.
This works with any C++11-compliant compilers (e.g. compilers like gcc-4.9.4) and still produces nearly identical assembly to a basic for-loop counterpart.
Note: The iota helper function is just for feature-parity with the C++20 std::views::iota solution; but realistically, you could also directly construct an iota_range{...} instead of calling iota(...). The former just presents an easy upgrade path if a user wishes to switch to C++20 in the future.
The KISS version...
for (int _i = 0; _i < 10; ++_i) {
const int i = _i;
// use i here
}
If your use case is just to prevent accidental modification of the loop index then this should make such a bug obvious. (If you want to prevent intentional modification, well, good luck...)
Couldn't you just move some or all the content of your for loop in a function that accepts i as a const?
Its less optimal than some solutions proposed, but if possible this is quite simple to do.
Edit: Just an example as I tend to be unclear.
for (int i = 0; i < 10; ++i)
{
looper( i );
}
void looper ( const int v )
{
// do your thing here
}
If you do not have access to c++20, typical makeover using a function
#include <vector>
#include <numeric> // std::iota
std::vector<int> makeRange(const int start, const int end) noexcept
{
std::vector<int> vecRange(end - start);
std::iota(vecRange.begin(), vecRange.end(), start);
return vecRange;
}
now you could
for (const int i : makeRange(0, 10))
{
std::cout << i << " "; // ok
//i = 100; // error
}
(See a Demo)
Update: Inspired from the #Human-Compiler's comment, I was wondering weather the given answers have any difference in the case of performance. It turn out that, except for this approach, for all other approaches surprisingly have same performance (for the range [0, 10)). The std::vector approach is the worst.
(See Online Quick-Bench)
And here is a C++11 version:
for (int const i : {0,1,2,3,4,5,6,7,8,9,10})
{
std::cout << i << " ";
// i = 42; // error
}
Here is live demo
#include <cstdio>
#define protect(var) \
auto &var ## _ref = var; \
const auto &var = var ## _ref
int main()
{
for (int i = 0; i < 10; ++i)
{
{
protect(i);
// do something with i
//
printf("%d\n", i);
i = 42; // error!! remove this and it compiles.
}
}
}
Note: we need to nest the scope because of an astonishing stupidity in the language: the variable declared in the for(...) header is considered to be at the same nesting level as variables declared in the {...} compound statement. This means that, for instance:
for (int i = ...)
{
int i = 42; // error: i redeclared in same scope
}
What? Didn't we just open a curly brace? Moreover, it's inconsistent:
void fun(int i)
{
int i = 42; // OK
}
One simple approach not yet mentioned here that works in any version of C++ is to create a functional wrapper around a range, similar to what std::for_each does to iterators. The user is then responsible for passing in a functional argument as a callback which will be invoked on each iteration.
For example:
// A struct that holds the start and end value of the range
struct numeric_range
{
int start;
int end;
// A simple function that wraps the 'for loop' and calls the function back
template <typename Fn>
void for_each(const Fn& fn) const {
for (auto i = start; i < end; ++i) {
const auto& const_i = i;
fn(const_i); // or fn(std::as_const(i)); in C++17
}
}
};
Where the use would be:
numeric_range{0, 10}.for_each([](const auto& i){
std::cout << i << " "; // ok
//i = 100; // error
});
Anything older than C++11 would be stuck passing a strongly-named function pointer into for_each (similar to std::for_each), but it still works.
Here's a demo
Although this may not be idiomatic for for loops in C++, this approach is quite common in other languages. Functional wrappers are really sleek for their composability in complex statements and can be very ergonomic for use.
This code is also simple to write, understand, and maintain.
template<class T = int, class F>
void while_less(T n, F f, T start = 0){
for(; start < n; ++start)
f(start);
}
int main()
{
int s = 0;
while_less(10, [&](auto i){
s += i;
});
assert(s == 45);
}
maybe call it for_i
No overhead https://godbolt.org/z/e7asGj

What does range-for loop exactly do?

I'm working on a snake game program. I use a deque of Body in class Snake to represent a snake and of course Body is a struct I have defined. Here is part of the code:
struct Body { // one part of snake body
int x, y, direction;
Body() : x(0), y(0), direction(UP) { }
Body(int ix, int iy, int id) : x(ix), y(iy), direction(id) { }
};
class Snake {
protected:
std::deque<Body> body;
// other members
public:
auto begin()->std::deque<Body>::const_iterator const { return body.cbegin(); }
auto end()->std::deque<Body>::const_iterator const { return body.cend(); }
// other members
};
And in another function construct_random_food I need to generate a food and make sure it does not coincide with the snake. Here's the function definition:
Food construct_random_food(int gameSize, const Snake& snake) {
static std::random_device rd;
static std::uniform_int_distribution<> u(2, gameSize + 1);
static std::default_random_engine e(rd());
Food f;
while (1) {
f.x = u(e) * 2 - 1;
f.y = u(e);
bool coincide = 0;
for (const auto& bd : snake) // This causes an error.
if (bd.x == f.x && bd.y == f.y) {
coincide = 1; break;
}
if (!coincide) break;
}
return f;
}
An error is caused at the range-based for-loops line. It says that I'm trying to cast const Snake to Snake& (casting a low-level const away). I fix the problem by rewriting that line like this:
for (const auto& fd : const_cast<Snake&>(snake))
So I'm wondering what exactly a range-for do and what it needs. Does the error have anything to do with the begin() function in class Snake?
The problem is that your begin and end functions are not const.
auto begin()->std::deque<Body>::const_iterator const { return body.cbegin(); }
// this applies to the return type ^^^^^
You've applied the const qualifier to the return type, not to the calling object. Put the const qualifier before the trailing return type.
auto begin() const ->std::deque<Body>::const_iterator { return body.cbegin(); }
You can see the correct order in which you should place function qualifiers here: http://en.cppreference.com/w/cpp/language/function

C++ std::plus as template parameter

I wanna write a class for a binary indexed array,
which use two non-type default template parameter, op and identity.
And need to check the constraint that op(identity,identity) == identity.
My problem is,
I don't to how to specify op, my current solution does not compile.
‘class std::function<T(T, T)>’ is not a valid type for a template non-type parameter
how to to check op(identity,identity) == identity, currently I cannot verify, since failed on step 1, maybe static_assert?
So currently I use below workaround, but then I cannot specify op, eg, std::multiplies<int>.
Can anyone tell me how to achieve the goal?
#include <vector>
#include <functional>
// template <typename T = int, std::function<T(T,T)> op = std::plus<T>(), const T identity = T()>
template <typename T = int, const T identity = T()> // currently workaround
class BIT { // binary indexed array
const std::function<T(T,T)> op = std::plus<T>(); // currently workaround
public:
BIT(std::vector<T> value) : value(value), prefixSum(value.size() + 1, identity) {
for (size_t i = 1; i < prefixSum.size(); ++i) {
incrementNodeByValue(i, value[i-1]);
}
// print(prefixSum,"prefixSum");
}
T getSum(size_t i) {
auto sum = identity;
while (i) {
sum = op(sum, prefixSum(i));
i = firstSmallerAncestor(i);
}
return sum;
}
void incrementNodeByValue(size_t i, T x) {
while (i < prefixSum.size()) {
prefixSum[i] = op(prefixSum[i], x);
i = firstLargerAncestor(i);
}
}
private:
inline size_t firstLargerAncestor(size_t node) { return node + (node & -node); }
inline size_t firstSmallerAncestor(size_t node) { return node & (node - 1); }
std::vector<T> value;
std::vector<T> prefixSum;
};
int main() {
auto vec = std::vector<int> {5,1,15,11,52,28,0};
auto bit = BIT<>(vec);
}
The use of std::function here is a waste and seems to be the source of your confusion.
Note that templates may only be parameterized on typenames and values of integral types (char, int, long, etc). Here you're attempting to parameterize on a value of a std::function instantiation, which isn't an integral type. That said, you don't actually need to parameterize on a value in this case.
Because your constructor doesn't accept an argument to initialize the op member variable nor is it accessible via the interface, I gather it's safe to assume the operator is known at compile-time, is guaranteed immutable, and default constructible.
As such, I declared the op member to be of a parameter type called operation.
#include <functional>
#include <vector>
template< typename T = int,
typename operation = std::plus<T>,
const T identity = T() >
class BIT {
const operation op = operation();
static_assert( operation()(identity, identity) == identity );
std::vector<T> value;
std::vector<T> prefixSum;
inline size_t firstLargerAncestor(size_t node) { return node + (node & -node); }
inline size_t firstSmallerAncestor(size_t node) { return node & (node - 1); }
public:
BIT(std::vector<T> value) :
value(value),
prefixSum(value.size() + 1, identity) {
for (size_t i = 1; i < prefixSum.size(); ++i) {
incrementNodeByValue(i, value[i-1]);
}
}
T getSum(size_t i) {
auto sum = identity;
while (i) {
sum = op(sum, prefixSum(i));
i = firstSmallerAncestor(i);
}
return sum;
}
void incrementNodeByValue(size_t i, T x) {
while (i < prefixSum.size()) {
prefixSum[i] = op(prefixSum[i], x);
i = firstLargerAncestor(i);
}
}
};
live example
As a note, you'll likely want to define an identity template elsewhere to parameterized on an operation and value types to default the third parameter here. As is, it seems you'll almost always be defining all three parameters during instantiation.

why does range-v3 yield require default constructor

I am trying to understand, for what reasons does the yield family of functions require that class be default constructible?
In the following example, the vnums1 line compiles only if CNum has a default constructor. The vnums2 line does not require a default constructor.
I am using Visual Studio 2017 and Range-V3-VS2015. Thank you!
#include <range/v3/all.hpp>
struct CNum
{
// CNum() = default;
explicit CNum(int num) : m_num(num) {}
int m_num;
};
int main()
{
auto ints = ranges::view::ints(0, 10);
// this compiles only of CNum has a default constructor
auto vnums1 = ints
| ranges::view::for_each([](int num) { return ranges::yield_if(num % 2, CNum(num)); })
| ranges::to_vector;
// this compiles even if CNum does not have a default constructor
auto vnums2 = ints
| ranges::view::remove_if([](int num) { return num % 2 == 0; })
| ranges::view::transform([](int num) { return CNum(num); })
| ranges::to_vector;
return 0;
}
We just changed the code to not require DefaultConstructible. git pull and enjoy.
The reason you need to default constructor to use ranges::yield_if is that the machinery it uses requires the type to be default constructable. If we look at the code we have
struct yield_if_fn
{
template<typename V>
repeat_n_view<V> operator()(bool b, V v) const
{
return view::repeat_n(std::move(v), b ? 1 : 0);
}
};
/// \relates yield_if_fn
/// \ingroup group-views
RANGES_INLINE_VARIABLE(yield_if_fn, yield_if)
And we can see that it calls view::repeat_n. Looking at that code we get
repeat_n_view<Val> operator()(Val value, std::ptrdiff_t n) const
{
return repeat_n_view<Val>{std::move(value), n};
}
And if we look at repeat_n_view we have
// Ordinarily, a view shouldn't contain its elements. This is so that copying
// and assigning ranges is O(1), and also so that in the event of element
// mutation, all the copies of the range see the mutation the same way. The
// repeat_n_view *does* own its lone element, though. This is OK because:
// - O(N) copying is fine when N==1 as it is in this case, and
// - The element is immutable, so there is no potential for incorrect
// semantics.
struct repeat_n_view
: view_facade<repeat_n_view<Val>, finite>
{
private:
friend range_access;
Val value_;
std::ptrdiff_t n_;
// ...
public:
repeat_n_view() = default;
constexpr repeat_n_view(Val value, std::ptrdiff_t n)
: value_(detail::move(value)), n_((RANGES_EXPECT(0 <= n), n))
{}
constexpr std::size_t size() const
{
return static_cast<std::size_t>(n_);
}
};
We see from the comment that this was a design decision and because of this design you need your type to be default constructable. Eric describes the type required as being SemiRegular which is documented as
it needs to be default constructable, copy and move constructable, and destructable.