Using Template Specialization To Discriminate Between Values And Arrays (of Values) - c++

I am trying to construct a device which will do one thing for a value (specifically, a native type) and another thing for a C-style array of primitives.
This is what I have now, which does not do what I wish.
#include <cstdlib>
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
template<class V> void dump_buf(const V& val)
{
cout << "val = " << val << "\n";
}
template<class A> void dump_buf(const A ary[])
{
cout << "ary size = " << sizeof(ary) << "\n";
for( size_t i = 0; i < sizeof(ary); ++i )
cout << "\t" << i+1 << " : " << ary[i] << "\n";
}
int main()
{
cout << "\n";
int i = 42;
float f = 3.14f;
unsigned fib[] = {0,1,1,2,3,5};
char s[] = "hello";
dump_buf(i);
dump_buf(f);
dump_buf(s);
dump_buf(fib);
}
This doesn't work because ary is of type pointer-to-something, not array-of-something. The output for the above (Intel, x64 compile, VS9) is:
val = 42
val = 3.14
ary size = 8
1 : h
2 : e
3 : l
4 : l
5 : o
6 :
7 : ╠
8 : ╠
ary size = 8
1 : 0
2 : 1
3 : 1
4 : 2
5 : 3
6 : 5
7 : 3435973836
8 : 3435973836
But I want the output to be:
val = 42
val = 3.14
ary size = 6
1 : h
2 : e
3 : l
4 : l
5 : o
6 :
ary size = 6
1 : 0
2 : 1
3 : 1
4 : 2
5 : 3
6 : 5
Note that the desired output for the string is 6 characters rather than 5 because of the null-terminator, which is part of the array.
Is there any way to get this to work, using only Standard C++ and no additional libraries?
Nearly any Standard-conformant technique would be acceptable. Overloading, template specialization, overriding, class templates... all are OK. I'm wide open to almost any technique that will accomplish my goal.

This should do the trick:
template<class A, size_t S> void dump_buf(const A (& ary)[S])
{
cout << "ary size = " << S << "\n";
for( size_t i = 0; i < S; ++i )
cout << "\t" << i+1 << " : " << ary[i] << "\n";
}
By taking a reference to an array, rather than a pointer to the start of an array, the size is known and available as an inferred template argument.
Also, remember that sizeof gives the size in bytes, so when you do want the number of objects in an array (and can't or don't want to use a template like this), you want sizeof(ary)/sizeof(*ary). In both cases, you need a real array, not a pointer to an array, which has lost all knowledge of the array's size.

Related

How can I convert a std::string to std::vector?

I have some code which I need to serialize a vector into bytes, then send it to a server. Later on, the the server replies with bytes and I need to serialize it back into a vector.
I have managed to serialize into bytes okay, but converting back into a vector is getting the wrong values:
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<double> v = {1, 2, 3};
std::cout << "Original vector: " << std::endl;
for (auto i : v) {
std::cout << i << " ";
}
std::cout << std::endl;
std::string str((char *)v.data(), sizeof(v[0])*v.size());
std::cout << "Vector memory as string: " << std::endl << str << std::endl;
std::cout << "Convert the string back to vector: " << std::endl;
auto rV = std::vector<double>(&str[0], &str[str.size()]);
for (auto i : rV){
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
This outputs:
Original vector:
1 2 3
Vector memory as string:
�?##
Convert the string back to vector:
0 0 0 0 0 0 -16 63 0 0 0 0 0 0 0 64 0 0 0 0 0 0 8 64
What is going wrong with my conversion from a string to a vector, and how can I fix it?
Here is a link to run the code.
Like this
std::vector<double>((double*)str.data(), (double*)(str.data() + str.size()));
Basically the same as your code, but I've added some casts. In your version the chars get converted directly into doubles (as if you had written rV[0] = str[0] etc) and the vector is sizeof(double) times too big.

c++ why is move/forward necessary in moving constructor [duplicate]

This question already has answers here:
Why do you use std::move when you have && in C++11? [duplicate]
(4 answers)
Closed 3 years ago.
After constructing an object with a moving constructor, the new object should "steal" the resources of the "source" object, which is then left in an indefinite (but valid) state.
For example:
#include <iostream>
#include <vector>
template <class T>
void print(const std::vector<T>& v)
{
std::cout << "size = " << v.size() << " vector = ";
for (const auto& x : v)
std::cout << x << " ";
std::cout << std::endl;
}
int main()
{
std::vector<int> data(10, 3);
std::cout << "data:" << std::endl;
print(data);
std::vector<int> data2(std::move(data));
std::cout << "data2:" << std::endl;
print(data2);
std::cout << "data after moving:" << std::endl;
print(data);
return 0;
}
See it live on Coliru.
As far as I know the standard does not specify the content of data after having called the moving constructor, however one would expect that the resources of data have been stolen by data2. And indeed, the output the program above shows that:
data:
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
data2:
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
data after moving:
size = 0 vector =
Now consider a slight variation of the above program:
#include <iostream>
#include <vector>
class A {
std::vector<int> m_data;
public:
A(std::vector<int>&& data) : m_data{data} { }
const std::vector<int>& data() const { return m_data; }
};
template <class T>
void print(const std::vector<T>& v)
{
std::cout << "size = " << v.size() << " vector = ";
for (const auto& x : v)
std::cout << x << " ";
std::cout << std::endl;
}
int main()
{
std::vector<int> data(10, 3);
std::cout << "data:" << std::endl;
print(data);
A x{std::move(data)};
std::cout << "x.data():" << std::endl;
print(x.data());
std::cout << "data after moving:" << std::endl;
print(data);
return 0;
}
See it live on Coliru.
I am surprised by output of the program:
data:
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
x.data():
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
data after moving:
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
It looks like the vector data has been just copied to A::m_data rather then being moved.
If I substitute the moving constructor of A with
A(std::vector<int>&& data) : m_data{std::move(data)} { }
(see it live on Coliru)
or with
A(std::vector<int>&& data) : m_data{std::forward<std::vector<int>&&>(data)} { }
(see it live on Coliru)
then the output of the program resembles that of the first code
data:
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
x.data():
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
data after moving:
size = 0 vector =
In other words, it seems that either std:move or std::forward are necessary to effectively call the moving constructor of A::m_data. Both std::move and std::forward return a static_cast to std::vector<int>&&, but the argument of the moving constructor of A is already a rvalue.
Why is an additional std::move or std::forward necessary?
First your should know that A::A(std::vector<int>&& data) means that data is rvalue reference to std::vector<T>, just means reference not a call to move constructor,
and A(std::vector<int>&& data) : m_data{data} { } just calls copy constructor of m_data because data itself is a named value not a r value temporary in scope of A::A hence a std::move or std::forward is necessary.

Most 'functional' way to sum pairs of elements from a vector using C++17 or later?

I'd like some suggestions for the most terse and 'functional' way to gather pairs of successive elements from a vector (1st and 2nd, 3rd and 4th, etc.) using modern C++. Assume the vector is of arbitrary but even length. For the examples I'm pulling together, I'm summing the elements of each pair but that's not the main problem. I should add I'll use STL only, no Boost.
In Python I can zip them into 2-tuples via an iterator with
s = range(1,11)
print([(x + y) for x,y in zip(*[iter(s)] * 2)])
In Perl 5 I can peel off pairs with
use List::Util qw/pairs sum/;
use feature 'say';
#s = 1 .. 10;
say sum #$_ foreach (pairs #s);
In Perl 6 I can shove them two at a time into a block with
my #s = 1 .. 10;
for #s -> $x, $y { say $x + $y; }
and in R I can wrap the vector into a 2-column array and sum the rows with
s <- 1:10
print(apply(matrix(s, ncol=2, byrow=TRUE), 1, sum))
I am not fluent in C++ and my solution uses for(;;). That feels too much like C.
#include <iostream>
#include <vector>
#include <numeric> // std::iota
int main() {
std::vector<int> s(10);
std::iota(s.begin(), s.end(), 1);
for (auto p = s.cbegin(); p != s.cend(); p += 2)
std::cout << (*p + *(p + 1)) << std::endl;
}
The output of course should be some variant of
3
7
11
15
19
Using range-v3:
for (auto v : view::iota(1, 11) | view::chunk(2)) {
std::cout << v[0] + v[1] << '\n';
}
Note that chunk(2) doesn't give you a compile-time-fixed size view, so you can't do:
for (auto [x,y] : view::iota(1, 11) | view::chunk(2)) { ... }
Without using range-v3 I was able to do this with either a function or a lambda template. I'll show the lambda version here.
#include <iostream>
#include <string>
#include <vector>
template<typename T>
auto lambda = [](const std::vector<T>& values, std::vector<T>& results) {
std::vector<T> temp1, temp2;
for ( std::size_t i = 0; i < values.size(); i++ ) {
if ( i & 1 ) temp2.push_back(values[i]); // odd index
else temp1.push_back(values[i]); // even index
}
for ( std::size_t i = 0; i < values.size() / 2; i++ )
results.push_back(temp[i] + temp[2]);
};
int main() {
std::vector<int> values{ 1,2,3,4,5,6 };
for (auto i : values)
std::cout << i << " ";
std::cout << '\n';
std::vector<int> results;
lambda<int>(values, results);
for (auto i : results)
std::cout << i << " ";
std::cout << '\n';
std::vector<float> values2{ 1.1f, 2.2f, 3.3f, 4.4f };
for (auto f : values2)
std::cout << f << " ";
std::cout << '\n';
std::vector<float> results2;
lambda<float>(values2, results2);
for (auto f : results2)
std::cout << f << " ";
std::cout << '\n';
std::vector<char> values3{ 'a', 'd' };
for (auto c : values3)
std::cout << c << " ";
std::cout << '\n';
std::vector<char> results3;
lambda<char>(values3, results3);
for (auto c : results3)
std::cout << c << " ";
std::cout << '\n';
std::vector<std::string> values4{ "Hello", " ", "World", "!" };
for (auto s : values4)
std::cout << s;
std::cout << '\n';
std::vector<std::string> results4;
lambda<std::string>(values4, results4);
for (auto s : results4)
std::cout << s;
std::cout << '\n';
return EXIT_SUCCESS;
}
Output
1 2 3 4 5 6
3 7 11
1.1 2.2 3.3 4.4
3.3 7.7
a d
┼
Hello World!
Hello World!
At the risk of sounding like I'm trying to be clever or annoying, I say this is the answer:
print(sums(successive_pairs(range(1,11))));
Now, of course, those aren't built-in functions, so you would have to define them, but I don't think that is a bad thing. The code clearly expresses what you want in a functional style. Also, the responsibility of each of those functions is well separated, easily testable, and reusable. It isn't necessary to use a lot of tricky specialized syntax to write code in a functional style.

How reinterpret_cast works for flattening a std::vector?

I would like to represent a std::vector of a structure containing several integers as a "flatten" vector of integers, without copying the data.
I tried something with a reinterpret_cast as shown below:
#include <vector>
#include <iostream>
struct Tuple
{
int a, b, c;
};
int main()
{
// init
std::vector<Tuple> vec1(5);
for(size_t i=0; i<vec1.size(); ++i)
{
vec1[i].a = 3 * i + 0;
vec1[i].b = 3 * i + 1;
vec1[i].c = 3 * i + 2;
}
// flattening
std::vector<int>* vec2 = reinterpret_cast<std::vector<int>*>(&vec1);
// print
std::cout << "vec1 (" << vec1.size() << ") : ";
for(size_t i=0; i<vec1.size(); ++i)
{
std::cout << vec1.at(i).a << " " << vec1.at(i).b << " " << vec1.at(i).c << " ";
}
std::cout << std::endl;
std::cout << "vec2 (" << vec2->size() << ") : ";
for (size_t j = 0; j < vec2->size(); ++j)
{
std::cout << vec2->at(j) << " ";
}
std::cout << std::endl;
return 0;
}
which works well since the output is:
vec1 (5) : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
vec2 (15) : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
My questions are :
Is this behavior compiler dependent? (I am using g++ 6.3.0)
How vec2 knows that the size of the vector is 15 and not 5?
Is their any other solution avoiding the use of reinterpret_cast? (If I "accidentally" add a double member to Tuple, the resulting issue could be hard to track...)
If vec1 has a specific allocator: std::vector<Tuple,A<Tuple>>, what should be the type of vec2? std::vector<int> or std::vector<int,A<int>> or std::vector<int,A<Tuple>>?
You can't legally reinterpret_cast the entire vector to a different type of vector. But you can legally cast a pointer to struct to a pointer to the first element of that struct. So this works:
std::vector<Tuple> vec1(5);
int* vec2 = &vec1.front().a;
size_t vec2_size = vec1.size() * sizeof(vec1[0]) / sizeof(vec2[0]);
for (size_t j = 0; j < vec2_size; ++j)
{
std::cout << vec2[j] << " ";
}
You need to make sure there's no padding in Tuple, so:
static_assert(sizeof(Tuple) == 3 * sizeof(int), "Tuple must be 3 ints");
To answer your bulleted questions:
Is this behavior compiler dependent?
Your code was illegal.
How vec2 knows that the size of the vector is 15 and not 5?
You got lucky, your code was illegal.
Is their any other solution avoiding the use of reinterpret_cast?
See above.
If vec1 has a specific allocator: std::vector>, what should be the type of vec2?
Same as above, int*.

How to write a n-ary negator?

The usefulness of unary and binary negators is easily understandable.
Example with unary negator (not1):
class Even
{
public:
bool operator() (const int& x) const { return x % 2 == 0; }
typedef int argument_type;
};
int values[] = { 9, 1, 8, 2, 7, 3, 6, 4, 5 };
int even = count_if(values, values + 9, Even());
int odd = count_if(values, values + 9, not1(Even())); // <= unary negator
cout << "We have " << even << " even elements in the array.\n";
cout << "We have " << odd << " odd elements in the array.\n";
Output:
We have 4 even elements in the array.
We have 5 odd elements in the array.
Example with binary negator (not2):
int values[] = { 9, 1, 8, 2, 7, 3, 6, 4, 5 };
// original array
for (int i : values)
cout << i << " ";
cout << "\n";
// array in ascending order
sort(values, values + 9, less<int>());
for (int i : values)
cout << i << " ";
cout << "\n";
// array in descending order
sort(values, values + 9, not2(less<int>())); // <= binary negator
for (int i : values)
cout << i << " ";
cout << "\n\n";
Output:
9 1 8 2 7 3 6 4 5
1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1
What about n-ary negators (not3, not4, not5 ... notn) ?
Let's assume that I need to count the number of elements that are not between two numbers (lower bound limit and upper bound limit) in a collection (maybe an array).
.
int elems_betweem = count_if(values, values + n, not3(bind(Between<int>(), _1, lowerValue, upperValue)));
.
How do I write the not3 negator?
Even more, do we have a generic not as a replacer of not1 and not2 in the same way as bind vs bind1st and bind2nd ?
Thank you
Since C++17 std::not_fn will be available:
auto between = [](int value, int lowerValue, int upperValue) {
return lowerValue < value && value < upperValue;
};
int elems_between = std::count_if(std::cbegin(values), std::cend(values),
std::bind(std::not_fn(between), std::placeholders::_1, lowerValue, upperValue));
wandbox example
How do I write the not3 negator?
A C++03 compliant example:
template<class Pred>
class ternary_predicate {
Pred pred;
public:
ternary_predicate(Pred pred): pred(pred){}
template<class A, class B, class C>
bool
operator()(A const& a, B const& b, C const& c) const {
return !pred(a, b, c);
}
};
template<class Pred>
ternary_predicate<Pred>
not3(Pred pred) {
return ternary_predicate<Pred>(pred);
}
Even more, do we have a generic not as a replacer of not1 and not2 in the same way as bind vs bind1st and bind2nd ?
We will, once C++17 is official. It is proposed to introduce std::not_fn as a replacement for std::not1 and std::not2 which will then be deprecated.
If you feel impatient, it's should not be difficult to implement yourself in C++14:
template<class Pred>
auto
not_fn(Pred&& pred) {
return [pred=std::forward<Pred>(pred)](auto&&... args){
return !pred(std::forward<decltype(args)>(args)...);
};
}
You can write your own std::not_fn as long as it's not available:
template <typename T>
struct not_func
{
template <typename...Args>
constexpr bool operator()(const Args&...args) const { return !T{}(args...); }
};
Example usage:
int main()
{
bool a1 = std::less<int>{}(1, 2);
bool a2 = not_func<std::less<int>>{}(1, 2);
bool b1 = Even{}(1);
bool b2 = not_func<Even>{}(1);
std::cout
<< "a1 = " << (a1 ? "true" : "false") << "\n"
<< "a2 = " << (a2 ? "true" : "false") << "\n"
<< "b1 = " << (b1 ? "true" : "false") << "\n"
<< "b2 = " << (b2 ? "true" : "false") << "\n";
}
[On Coliru]
[On Godbolt]
I haven't tested all possible variants so this might still be buggy.