Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Herb Sutter states Almost Always Auto and I have the following code:
using count_t = int;
count_t get_count() { ... };
const auto count = get_count();
for (decltype(count) i = 0; i < count; i++) {
// Do the stuff
}
Essentially, using decltype() allows me to write a for loop that may use any integer type (hoping that get_count() would never return floating point) without any modifications in a client code of get_count() function and avoid compilation warnings like "signed-unsigned" mismatch.
My question is: is this form acceptable at all in an assumption that count_t may be redefined in future?
If using Boost is an option, you can avoid all the noise
#include <boost/range/irange.hpp>
for(auto i : boost::irange(get_count()))
The single argument version of boost::irange was introduced in 1.68, so you will need to copy the implementation for earlier versions.
To still be AAA, you might go to:
for (auto i = decltype(count){}; i != count; ++i) { /*..*/ }
template<class T>
struct indexer_t {
T t;
T operator*()const{return t;}
void operator++(){++t;}
friend bool operator==(indexer_t const& lhs, indexer_t const& rhs) {
return lhs.t==rhs.t;
}
friend bool operator!=(indexer_t const& lhs, indexer_t const& rhs) {
return lhs.t!=rhs.t;
}
};
template<class It>
struct range_t {
It b,e;
It begin() const { return b; }
It end() const { return e; }
};
template<class T>
range_t<indexer_t<T>> count_over( T const& s, T const& f ) {
return { {s}, {f} };
}
template<class T>
range_t<indexer_t<T>> count_upto( T const& t ) {
return count_over<T>( 0, t );
}
for (auto i : count_upto(count))
{
// Do the stuff
}
indexer_t and range_t can be improved; they are both minimal implementations.
Here is another alternative. I won't declare it to be better or worse than your own suggestion:
for (auto i = 0 * count; i < count; i++) {
Note that, as mentioned in comments, this behaves differently compared to yours in case type of count is smaller than int in which cases my i is promoted.
That said, index based loops can usually (perhaps always?) be converted to an iterator based loop, where auto deduction is more natural.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm learning C++ Expression Templates these days, I've read a lot of articles. Still confused about how to design an express template.
Is there any standard way(steps) when we design Expression Templates, in other words , how to design, including what classes should I create and what operations should I performed in specific functions?
Let's say Matrix computations.
I know how to write it via overloading C++ operators, but after I finish it by overloading coperators I don't know how to write it using Expression Templates.
The main idea of having an expression template is to use lazy evaluation, i.e. only compute result when using an expression that uses the addition, subtraction, etc. expression for specific index, instead of computing the result for all the values of the arrays in the constructor.
Have a "sum" class with two variable members, where each represent the arrays that you want to add (As you add more than two arrays, this class will be used "recursively" as I'll show below). For this you need to have a class with 2 template arguments for each member, and have an operator[] which returns the addition of both arrays for specific location, i.e.
int operator[](const int i) const
{
return a[i] + b[i];
}
Have a "starting" class which initializes the values of your arrays. Note that this class is different from the above, as it will only store 1 array. Also this class must implement operator[] as follows:
int operator[](const int i) const
{
return starting_vector[i];
}
Have an overload operator+ to add your "starting" vector (from 2 bullet) with other ones, and to store them in the "sum" class (from 1 bullet) as:
template <typename A, typename B>
VectorSum<A, B> operator+(const A v1, const B v2)
{
return VectorSum<A, B>{v1, v2};
}
Below is a complete example that compiles:
#include <initializer_list>
#include <iostream>
#include <stdexcept>
#include <vector>
class Vector
{
public:
explicit Vector(const std::initializer_list<int>& vec)
{
for (const auto x : vec)
{
starting_vector.push_back(x);
}
}
int operator[](const int i) const
{
return starting_vector[i];
}
std::size_t size() const
{
return starting_vector.size();
}
private:
std::vector<int> starting_vector;
};
template <typename A, typename B>
class VectorSum
{
public:
VectorSum(const A& other_a, const B& other_b):
a{other_a}, b{other_b}
{
if (other_a.size() != other_b.size())
{
throw std::invalid_argument{"must be same sizes"};
}
}
int operator[](const int i) const
{
return a[i] + b[i];
}
std::size_t size() const
{
return a.size();
}
private:
const A a;
const B b;
};
template <typename A, typename B>
VectorSum<A, B> operator+(const A v1, const B v2)
{
return VectorSum<A, B>{v1, v2};
}
int main()
{
Vector v1{{1,2,3,4,100}};
Vector v2{{1,2,3,4,1}};
Vector v3{{1,2,3,4,2}};
Vector v4{{1,2,3,10,5}};
VectorSum<VectorSum<VectorSum<Vector, Vector>, Vector>, Vector> sum {v1 + v2 + v3 + v4};
std::cout << sum[0] << std::endl;
}
There is many primitive structs (several hundreds), that are used to transfer data between two components (for example a player and a server). There are no methods in them, just raw data.
The task is to write all requests and answers to be able to replay a player scenario without a server (we remember all question and all answers, that are pure functions).
So the task is put this structs in map without comparator. Now we use memcmp, it allows not to think about changes in this structs and it is compact, but there are too many problems with padding and etc.
Is it possible to get smth like getHashValue or any default comparator with metaprogramming in c++?
Conditions:
1) I do not want to create a comparator for each struct.
2) I want to have an error if a field was added or deleted if it breaks existing behavior and needs fix.
3) I don't want to change header files with struct definitions.
Example of a struct
struct A {
int a;
int b;
c c;
}
bool operator<(const A& a1, const A& a2)
{
if (a1.a != a2.a) return a1.a < a2.a;
if (a1.b != a2.b) return a1.b < a2.b;
if (a1.c != a2.c) return a1.c < a2.c;
return false;
}
I can consider other languages to implement this exact part (collect questions/answers), if it will not require to describe all this structs on that language again.
In C++17 you can pull this off if you are willing to (A) hard code how many elements are in each struct somewhere, and (B) write or generate code for each count of number of elements in the struct.
template<std::size_t N>
using size_k = std::integral_constant<std::size_t, N>;
template<class T>
auto auto_tie( size_k<0>, T&& t ) {
return std::tie();
}
template<class T>
auto auto_tie( size_k<1>, T&& t ) {
auto& [ x0 ] = std::forward<T>(t);
return std::tie( x0 );
}
template<class T>
auto auto_tie( size_k<2>, T&& t ) {
auto& [ x0, x1 ] = std::forward<T>(t);
return std::tie( x0, x1 );
}
// etc
now, in the namespace of the struct in question, write
struct foo {
int x;
};
struct bar {
int a, b;
};
size_k<1> elems( foo const& ) { return {}; }
size_k<2> elems( bar const& ) { return {}; }
an elems function that return the size_k counting how many elements.
Now in the namespace of the structs, write:
template<class T, class Size=decltype(elems(std::declval<T const&>()))>
bool operator<( T const& lhs, T const& rhs ) {
return auto_tie( Size{}, lhs ) < auto_tie( Size{}, rhs );
}
and you are done.
Test code:
foo f0{1}, f1{2};
bar b0{1,2}, b1{-7, -3};
std::cout << (f0<f1) << (f1<f0) << (f0<f0) << "\n";
std::cout << (b0<b1) << (b1<b0) << (b0<b0) << "\n";
Live example.
Getting further than this will require writing 3rd party tools or waiting for reflection extension to C++, maybe in C++20 or 23.
If you get elems wrong, I believe the structured bindings code in auto_tie should generate an error.
I suppose you could write your own compare operator based upon memcmp.
bool operator<(const A &lhs, const A &rhs) {
return memcmp(&lhs, &rhs, sizeof(A)) < 0;
}
Off course, writing these for each object might be a burden, so you could write a template for this. Though without some SFINAE it will cover too much types.
#include <type_traits>
#include <cstring>
template<typename T>
std::enable_if_t<std::is_pod_v<std::decay_t<T> //< Check if POD
&& !std::is_fundamental_v<std::decay_t<T>>>, //< Don't override for fundamental types like 'int'
bool>
operator<(const T &lhs, const T &rhs) {
return memcmp(&lhs, &rhs, sizeof(std::decay_t<T>)) < 0;
}
EDIT: Note that this technique requires you to zero-initialize the structs.
Looks like the best way to do it is to write a generator, that will generate .h and .cpp with bool operator< for all types in this header file. Then add this project as pre-build step to the main.
It doesn't look like a nice solution, but it allows to avoid hand-written code duplication and will support adding/removing new structs/fields. So I didn't find a better way.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am trying to change the order of a set in a particular configuration :
a customObject has the following form
class CustomObject{
public:
...
std::set<CustomObject*> container;
};
and I would like to keep permanently the property telling that the container is sorted in the following order :
elt1 & elt2 are elements of container,
and
elt1 < elt2 iff elt1.container.size()<elt2.container.size()
I know I have to use
struct cmpStruct {
bool operator() (int const & lhs, int const & rhs) const
{
return lhs > rhs;
}
};
as described Is the std::set iteration order always ascending according to the C++ specification?
But I don't know how to do to access the "this" inside the structure
Thanks a lot for your help
Something like that?
class CustomObject{
public:
CustomObject(int _x) : x(_x) {};
int x;
};
struct cmpStruct {
bool operator() (const CustomObject* lhs, const CustomObject* rhs) const
{
return lhs->x > rhs->x;
}
};
int main(int argc, char* argv[])
{
std::set<CustomObject*, cmpStruct> container;
CustomObject a(10);
CustomObject b(20);
CustomObject c(5);
container.insert(&a);
container.insert(&b);
container.insert(&c);
for(auto co : container) {
std::cout << co->x << std::endl;
}
return 0;
}
Output:
20
10
5
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
Can anyone explain me the advantages of function poiner?
I know that there are many possible duplicates with my question but they only explain in words , that's not very helpful , I need an example of the case that not using the function pointer compare to the case of using the function pointer.
Thanks a lot.
How about mapping data to behaviour, things like:
void DoIt();
void DontDoIt();
std::map<std::string, std::function<void()> word_map {
{"DoIt", DoIt},
{"DontDoIt", DontDoIt}
};
std::string word;
// ... get "DoIt" or "DontDoIt" into word
word_map[word](); // execute correct function
Simple example : suppose you have N record comprising of names and phone numbers.
You're asked to sort
based on names
based on phone numbers
A nice approach would just be to vary a comparison function passed as a function pointer inside a sorting routine.
void sort( records r[], int N,
bool (*fptr)( const record& lhs, const record& rhs ) ) { }
If you won't use function pointer you'll end up coding same logic merely for two different comparison function.
void sort_by_name( records r[], int N) { }
void sort_by_phoneno( records r[], int N) { }
By using a function pointer you can, for example, prevent code duplication.
Without function pointers:
void AddOneToVectorElements( vector<int> v )
{
// implementation
}
void MultiplyVectorElementsByTwo( vector<int> v )
{
// implementation
}
// usage
AddOneToVectorElements(v);
MultiplyVectorElementsByTwo(v);
Using function pointers:
typedef int (*func)(int);
int TransformVecotr ( vector<int> v, func f)
{
// implementation by application of f to every element
}
int AddOne(int x)
{
return x + 1;
}
int MultiplyByTwo(int x)
{
return 2 * x;
}
// usage
TransformVecotr(v, &AddOne);
TransformVecotr(v, &MultiplyByTwo);
In C++11 there are lambda functions and they make the whole thing even more convenient.
The key point is that function pointers are used "under the hood" all the time in generic programming. One tends to forget this, because template argument deduction hides the function pointer syntax.
For example:
#include <algorithm>
#include <iterator>
bool f(int i)
{
return i == 1;
}
int main()
{
int arr[] = { 1, 1, 3 };
int count = std::count_if(std::begin(arr), std::end(arr), f);
}
The f in main's last line is a function pointer, because the std::count_if template function will accept anything that can be used with the () syntax. Quoting cppreference.com:
template< class InputIt, class UnaryPredicate >
typename iterator_traits<InputIt>::difference_type
count_if( InputIt first, InputIt last, UnaryPredicate p );
UnaryPredicate can be a function pointer, and is one in the example above.
The compiler just deduces its exact type, bool(*)(int), automatically when you pass f. Technically, you could also write the call like this:
// just for illustration:
std::count_if<int*, bool(*)(int)>(std::begin(arr), std::end(arr), f);
If there were no function pointers in C++, then you could not directly use functions as predicates in the standard-library algorithms. You'd instead have to wrap them in classes all the time:
#include <algorithm>
#include <iterator>
bool f(int i)
{
return i == 1;
}
struct Functor
{
bool operator()(int i) const
{
return f(i);
}
};
int main()
{
int arr[] = { 1, 1, 3 };
int count = std::count_if(std::begin(arr), std::end(arr), Functor());
}
This question already has answers here:
Closed 10 years ago.
The community reviewed whether to reopen this question 6 months ago and left it closed:
Original close reason(s) were not resolved
Possible Duplicate:
Find position of element in C++11 range-based for loop?
I have a vector and I would like to iterate it and, at the same time, have access to the indexes for each individual element (I need to pass both the element and its index to a function). I have considered the following two solutions:
std::vector<int> v = { 10, 20, 30 };
// Solution 1
for (std::vector<int>::size_type idx = 0; idx < v.size(); ++idx)
foo(v[idx], idx);
// Solution 2
for (auto it = v.begin(); it != v.end(); ++it)
foo(*it, it - v.begin());
I was wondering whether there might be a more compact solution. Something similar to Python's enumerate. This is the closest that I got using a C++11 range-loop, but having to define the index outside of the loop in a private scope definitely seems to be like a worse solution than either 1 or 2:
{
int idx = 0;
for (auto& elem : v)
foo(elem, idx++);
}
Is there any way (perhaps using Boost) to simplify the latest example in such a way that the index gets self-contained into the loop?
Here is some kind of funny solution using lazy evaluation. First, construct the generator object enumerate_object:
template<typename Iterable>
class enumerate_object
{
private:
Iterable _iter;
std::size_t _size;
decltype(std::begin(_iter)) _begin;
const decltype(std::end(_iter)) _end;
public:
enumerate_object(Iterable iter):
_iter(iter),
_size(0),
_begin(std::begin(iter)),
_end(std::end(iter))
{}
const enumerate_object& begin() const { return *this; }
const enumerate_object& end() const { return *this; }
bool operator!=(const enumerate_object&) const
{
return _begin != _end;
}
void operator++()
{
++_begin;
++_size;
}
auto operator*() const
-> std::pair<std::size_t, decltype(*_begin)>
{
return { _size, *_begin };
}
};
Then, create a wrapper function enumerate that will deduce the template arguments and return the generator:
template<typename Iterable>
auto enumerate(Iterable&& iter)
-> enumerate_object<Iterable>
{
return { std::forward<Iterable>(iter) };
}
You can now use your function that way:
int main()
{
std::vector<double> vec = { 1., 2., 3., 4., 5. };
for (auto&& a: enumerate(vec)) {
size_t index = std::get<0>(a);
double& value = std::get<1>(a);
value += index;
}
}
The implementation above is a mere toy: it should work with both const and non-const lvalue-references as well as rvalue-references, but has a real cost for the latter though, considering that it copies the whole iterable object several times. This problem could surely be solved with additional tweaks.
Since C++17, decomposition declarations even allow you to have the cool Python-like syntax to name the index and the value directly in the for initializer:
int main()
{
std::vector<double> vec = { 1., 2., 3., 4., 5. };
for (auto&& [index, value] : enumerate(vec)) {
value += index;
}
}
A C++-compliant compiler decomposes auto&& inferring index as std::size_t&& and value as double&.
As #Kos says, this is such a simple thing that I don't really see the need to simplify it further and would personally just stick to the traditional for loop with indices, except that I'd ditch std::vector<T>::size_type and simply use std::size_t:
for(std::size_t i = 0; i < v.size(); ++i)
foo(v[i], i);
I'm not too keen on solution 2. It requires (kinda hidden) random access iterators which wouldn't allow you to easily swap the container, which is one of the strong points of iterators. If you want to use iterators and make it generic (and possibly incur a performance hit when the iterators are not random access), I'd recommend using std::distance:
for(auto it(v.begin()); it != v.end(); ++it)
foo(*it, std::distance(it, v.begin());
One way is to wrap the loop in a function of your own.
#include <iostream>
#include <vector>
#include <string>
template<typename T, typename F>
void mapWithIndex(std::vector<T> vec, F fun) {
for(int i = 0; i < vec.size(); i++)
fun(vec[i], i);
}
int main() {
std::vector<std::string> vec = {"hello", "cup", "of", "tea"};
mapWithIndex(vec, [](std::string s, int i){
std::cout << i << " " << s << '\n';
} );
}