I'm trying to write a function like std::for_each, that in addition to the normal usage, can also take a std::function<bool (param)>. A false return value means that I want to break out of the loop. The code below is what I've gotten so far.
The second call to a.visit([&](int) -> void) does not compile when evaluating !visitor(i). Is it possible to make this work or am I barking up the wrong tree?
I'm using MSVC 2010 but want the code to be generally C++11 compatible.
#include <list>
#include <string>
#include <iostream>
struct A
{
std::list<int> _lst;
template<typename _F>
void visit(_F visitor)
{
for(std::list<int>::const_iterator it = _lst.begin(), end = _lst.end() ; it != end ; it++) {
int i = *it;
if (std::is_void<decltype(visitor(i))>::value) {
visitor(i);
} else {
if (!visitor(i)) { // <----- error C2171: '!' : illegal on operands of type 'void'
break;
}
}
}
}
};
int main(int argc, char* argv[])
{
A a;
// populate a
for (int i = 0 ; i < 10 ; i++) {
a._lst.push_back(i);
}
a.visit([](int i) -> bool {
std::cout << i << std::endl;
return i < 5;
});
a.visit([](int i) {
std::cout << i << std::endl;
});
}
Here's how I would implement for_almost_each; I'm using namespace std plus type aliases for readability purposes.
#include <algorithm>
#include <iterator>
#include <functional>
using namespace std;
template<class Iter, class Func>
Iter
for_almost_each_impl(Iter begin, Iter end, Func func, std::true_type)
{
for (auto i = begin; i!=end; ++i)
if (!func(*i))
return i;
return end;
}
template<class Iter, class Func>
Iter
for_almost_each_impl(Iter begin, Iter end, Func func, std::false_type)
{
for_each(begin, end, func);
return end;
}
template<class Iter, class Func>
Iter for_almost_each(Iter begin, Iter end, Func func)
{
using Val = typename iterator_traits<Iter>::value_type;
using Res = typename result_of<Func(Val)>::type;
return for_almost_each_impl(begin, end,
func,
is_convertible<Res, bool>{} );
}
I used is_convertible, as it seems to make more sense than is_same.
Your std::is_void needs to be done at compile time and can't be done inside the function body. This use of function overloading will work:
#include <list>
#include <string>
#include <iostream>
#include <type_traits> // missing header
struct A
{
std::list<int> _lst;
// wrapper for bool returning visitor
template<typename _F, typename Iter>
bool do_visit(_F visitor, Iter it, std::true_type)
{
return visitor(*it);
}
// wrapper for non-bool returning visitor
template<typename _F, typename Iter>
bool do_visit(_F visitor, Iter it, std::false_type)
{
visitor(*it);
return true;
}
template<typename _F>
void visit(_F visitor)
{
for (auto it = _lst.begin(), end = _lst.end() ; it != end ; it++) {
// select correct visitor wrapper function using overloading
if (!do_visit(visitor, it, std::is_same<bool, decltype(visitor(0))>())) {
break;
}
}
}
};
int main(int argc, char* argv[])
{
A a;
// populate a
for (int i = 0 ; i < 10 ; i++) {
a._lst.push_back(i);
}
a.visit([](int i) -> bool {
std::cout << i << std::endl;
return i < 5;
});
a.visit([](int i) {
std::cout << i << std::endl;
});
}
This lambda doesn't return a value, which is why you're getting an error that "visitor" is returning void:
a.visit([](int i) {
std::cout << i << std::endl;
});
You could make this work by rewriting as:
a.visit([](int i) -> bool {
std::cout << i << std::endl;
return true;
});
Related
Following is my code:
set<set<int,greater<int>>> output;
set<int,greater<int>> k;
k.insert(5);
output.insert(k);
Now how do I find out if element 5 is present in my 'output' set or not?
And how do I find out which set, inside my 'output' set, the element 5 belongs to?
Use a simple for loop:
size_t ii = 0;
for (const auto& inner : output) {
if (inner.count(5))
std::cout << "found in set " << ii << std::endl;
++ii;
}
There's a pre C++20 and a C++20 (using ranges) solution
Pre-C++20 I'm using std::find_if and set::find.
C++20 I'm using std::ranges::find_if and set::contains.
For the C++20 I'm also using std::optional std::reference_wrapper return type. And concepts, so it's a generic solution applicable to all sets and maps.
#include <set>
#include <algorithm>
template<typename T, typename Comp = std::less<T>>
std::set<T, Comp> const* findInSetOfSets(std::set<std::set<T, Comp>> const& setOfSets, T const& value) {
auto const it = std::find_if(cbegin(setOfSets), cend(setOfSets),
[&](std::set<T, Comp> const& set) { return set.find(value) != end(set); } );
if (it != cend(setOfSets)) return &*it;
return nullptr;
}
#include <optional>
#include <functional>
#include <type_traits>
template<typename T, typename U>
concept hasContains = requires(T& t, U& u) {
{ t.contains(u) } -> std::same_as<bool>;
};
template<std::ranges::input_range R, typename T,
typename U = std::remove_reference<R>::type::value_type>
requires hasContains<U, T>
[[nodiscard]] auto findCpp20(R&& r, T const& value) noexcept
->std::optional<std::reference_wrapper<U const>> {
auto it = std::ranges::find_if(r,
[&](U const& u) { return u.contains(value); } );
if (it != std::ranges::end(r)) return *it;
return std::nullopt;
}
#include <cstdio>
int main(){
std::set<std::set<int,std::greater<int>>> output;
std::set<int,std::greater<int>> k;
k.insert(5);
output.insert(k);
auto setPtr = findInSetOfSets(output, 5);
if (setPtr != nullptr) printf("set found!\n");
auto optionalSet = findCpp20(output, 5);
if (optionalSet.has_value()) printf("set found!\n");
}
godbolt
Here's a boolean function that looks for element p inside a set of sets s
bool findelem(int p, set<set<int>> const& s)
{
for (auto itr1= s.cbegin(); itr1 != s.cend(); ++itr1) {
for (auto itr2 = itr1->cbegin(); itr2 != itr1->cend(); ++itr2) {
if (*itr2==p) {
return true;
}
}
}
return false;
}
Is there a better way than the below code, to iterate over a container in either direction, using the same iterators?
#include <iostream>
#include <map>
int main()
{
const bool descend = false;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
std::map<int, int>::iterator startIter = descend ? --(mapp.end()) : mapp.begin();
std::map<int, int>::iterator endIter = descend ? --(mapp.begin()) : mapp.end();
while (startIter != endIter)
{
std::cout << startIter->first << std::endl;
descend ? --startIter : ++startIter;
}
}
Your code is invalid as this statement --(mapp.begin()) leads to UB. I would write a thin wrapper:
template<class Iter, class F>
void apply( Iter begin, Iter end, F f, bool forward )
{
while( begin != end )
f( forward ? *begin++ : *--end );
}
live example
or just simply rewrite your loop into:
auto begin = mapp.begin();
auto end = mapp.end();
while ( begin != end)
{
const auto &p = forward ? *begin++ : *--end;
std::cout << p.first << std::endl;
}
Is there a better way than the below code, to iterate over a container
in either direction, using the same iterators?
Yes. Use std::map::reverse_iterator. It will be a better way than the code you posted, but that will not be using the same iterators anymore, which was one of your requirements.
However, this will be less error-prone than the code you have written. In addition to that, you do not need to re-invent the wheel, if that is already in C++.
See output here
#include <iostream>
#include <map>
template<typename Iterator>
void print(const Iterator Begin, const Iterator End)
{
for(Iterator iter = Begin; iter != End; ++iter)
std::cout << iter->first << "\n";
}
int main()
{
const bool descend = true;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
descend ?
print(mapp.crbegin(), mapp.crend()):
print(mapp.cbegin(), mapp.cend());
return 0;
}
The image from cppreference.com will explain graphically, how does it work.
Write self-documenting code and it becomes simple. Break that loop out into its own function and call it with the appropriate iterators.
This is why we have "reverse iterators" they can be used to go backwards through a container by using the normal forward semantics.
#include <iostream>
#include <map>
template<typename I>
void printMapContainer(I begin, I end)
{
for (;begin != end; ++begin)
{
std::cout << begin->first << "\n";
}
}
int main()
{
const bool descend = false;
std::map<int, int> mapp;
mapp[1] = 1;
mapp[2] = 2;
mapp[3] = 3;
mapp[4] = 4;
if (descend) {
printMapContainer(mapp.rbegin(), mapp.rend());
}
else {
printMapContainer(mapp.begin(), mapp.end());
}
}
Given a std::map<,> m, I can do:
const auto iterator = m.find(k);
if (iterator != m.end())
{
const auto& value = iterator->second;
// ...
}
I'd like to do the same thing but with a boost::optional. Something like:
const auto o = boost::find_optional(m, k);
if (o)
{
const auto& value = o.get();
// ...
}
Is there something like that already?
A version that solves some of the limitations I noticed in other answers:
namespace stl {
namespace map {
namespace detail {
template <typename K, typename Map>
static auto lookup(K const &key, Map &&map) -> boost::optional<decltype(map.at(key)) &> {
auto it = map.find(key);
if (it != map.end())
return it->second;
return boost::none;
}
} // namespace detail
template <typename K, typename Map>
static decltype(auto) lookup(K const &key, Map &&map) {
return detail::lookup(key, std::forward<Map>(map));
}
template <typename K, typename Map>
static decltype(auto) lookup(boost::optional<K> const &key, Map &&map) {
return key ? (lookup)(*key, std::forward<Map>(map)) : boost::none;
}
}
using map::lookup;
//using set::lookup; // extended ideas
//using map::contains;
//using set::contains;
}
With a test program to demonstrate it:
Live On Coliru
#include <iostream>
#include <boost/optional/optional_io.hpp>
using stl::lookup;
template <typename Map>
void traverse(char const* startkey, Map const& m) {
std::cout << "\nTraverse from " << startkey << ":\n";
auto cursor = lookup(startkey, m);
do std::cout << "Lookup result: " << cursor << "\n";
while (cursor = lookup(cursor, m));
}
int main() {
std::map<std::string, std::string> m {
{ "Hello", "World" },
{ "World", "Peace" },
{ "Peace", "Troops" },
};
traverse("Hello", m);
// mutation:
if (auto peace = lookup("Peace", m))
*peace = "Love";
traverse("Hello", m);
}
Prints
Traverse from Hello:
Lookup result: World
Lookup result: Peace
Lookup result: Troops
Traverse from Hello:
Lookup result: World
Lookup result: Peace
Lookup result: Love
Here is my code:
#include <functional>
#include <iostream>
#include<vector>
using namespace std;
// vector iterator
template <class T> class vit
{
private:
//vector<T>::iterator it;
vector<T> m_v;
function<bool (T, T)> m_fptr;
int len, pos;
public:
vit(vector<T> &v) { this->m_v = v; len = v.size(); pos = 0;};
// it= v.begin(); };
bool next(T &i) {
//if(it == m_v.end()) return false;
if(pos==len) return false;
//i = *it;
i = m_v[pos];
//if(idle) { idle = false ; return true; }
//it++;
pos++;
return true;};
//bool idle = true;
void set_same(function<bool (T,T)> fptr) { m_fptr = fptr ;};
//void set_same(function<bool(int, int)> fun) { return ; }
bool grp_begin() {
return pos == 0 || ! m_fptr(m_v[pos], m_v[pos-1]); };
bool grp_end() {
return pos == len || ! m_fptr(m_v[pos], m_v[pos+1]); };
};
bool is_same(int a, int b) { return a == b; }
main()
{
vector<int> v ={ 1, 1, 2, 2, 2, 3, 1, 1, 1 };
int total;
for(auto it = v.begin(); it != v.end(); it++) {
if(it == v.begin() || *it != *(it-1)) {
total = 0;
}
total += *it;
if(it+1 == v.end() || *it != *(it+1)) {
cout << total << endl;
}
}
cout << "let's gry a group" <<endl;
vit<int> g(v);
int i;
while(g.next(i)) { cout << i << endl; }
cout << "now let's get really fancy" << endl;
vit<int> a_vit(v);
//auto is_same = [](int a, int b) { return a == b; };
a_vit.set_same(is_same);
//int total;
while(a_vit.next(i)) {
if(a_vit.grp_begin()) total = 0;
total += i;
if(a_vit.grp_end()) cout << total << endl ;
}
}
When I compile it with g++ -std=c++11 iter.cc -o iter, I get the result:
iter.cc: In function 'int main()':
iter.cc:63:17: error: reference to 'is_same' is ambiguous
a_vit.set_same(is_same);
^
iter.cc:37:6: note: candidates are: bool is_same(int, int)
bool is_same(int a, int b) { return a == b; }
^
In file included from /usr/include/c++/5.3.0/bits/move.h:57:0,
from /usr/include/c++/5.3.0/bits/stl_pair.h:59,
from /usr/include/c++/5.3.0/utility:70,
from /usr/include/c++/5.3.0/tuple:38,
from /usr/include/c++/5.3.0/functional:55,
from iter.cc:1:
/usr/include/c++/5.3.0/type_traits:958:12: note: template<class, class> struct std::is_same
struct is_same;
^
By way of explanation, I have created a class called 'vit'. It does two things: iterate over a vector, and determine if a new group has been reached.
The class function 'set_same' is supposed to store a function provided by the calling class to determine if two adjacent elements of a vector are in the same group. However, I can't seem to store the function in the class for future use by grp_begin() and grp_end() on account of the ostensible ambiguity of is_same.
What gives?
There is an is_same function defined by you and there is a struct is_same defined by the C++ Standard Library. Since you are using namespace std, your compiler doesn't know which is_same you meant to use.
It's what the error says: it's not clear whether you mean your is_same (in the global namespace) or the class template is_same (in namespace std).
You may disambiguate as follows:
::is_same
… with the leading :: meaning "in the global namespace".
Though you should consider putting your code in a namespace of its own.
Thanks guys. This is my first time touching C++ after more than a decade. I have cleaned up the code, and used a lambda to bring the "is_same" function closer to where it is called.
Did you spot the bug in my code? 'pos' was off-by-one when calling grp_begin() and grp_end(). Here is the revised code:
#include <functional>
#include <iostream>
#include <vector>
// vector iterator
template <class T> class vit
{
private:
std::vector<T> m_v;
std::function<bool (T, T)> m_fptr;
int len, pos;
public:
vit(std::vector<T> &v) { m_v = v; len = v.size(); pos = -1;};
bool next(T &val) {
pos++;
if(pos==len) return false;
val = m_v[pos];
return true;};
void set_same(std::function<bool (T,T)> fptr) { m_fptr = fptr ;};
bool grp_begin() {
return pos == 0 || ! m_fptr(m_v[pos], m_v[pos-1]); };
bool grp_end() {
return pos+1 == len || ! m_fptr(m_v[pos], m_v[pos+1]); };
};
main()
{
std::vector<int> v ={ 1, 1, 2, 2, 2, 3, 1, 1, 1 };
vit<int> a_vit(v);
std::function<bool (int, int)> is_same = [](int a, int b) { return a == b; };
a_vit.set_same(is_same);
int i, total;
while(a_vit.next(i)) {
if(a_vit.grp_begin()) total = 0;
total += i;
if(a_vit.grp_end()) std::cout << total << std::endl ;
}
}
My class definition isn't bullet-proof and could be better: if the user forgets to 'set-same', for example, they'll be referring a random memory address as a function.
Nevertheless, I'm pretty chuffed with my solution so far. The class caller is relieved of all the bookkeeping relating iterating over the vector, and working out if a group boundary has been crossed.
The calling code looks very compact and intuitive to me.I can see C++ being my go to language.
I asked How do I capture the results of a recursive function at compile-time?, but I think my approach was wrong.
I have a program like so:
#include <iostream>
#include <list>
std::list<unsigned int> recursive_case(std::list<unsigned int>& result, unsigned int& i) {
result.push_front(1 + (i % 10));
i /= 10;
return i != 0 ? recursive_case(result, i) : result;
}
std::list<unsigned int> initial_case(unsigned int i) {
std::list<unsigned int> result;
result.push_back(i % 10);
i /= 10;
return i != 0 ? recursive_case(result, i) : result;
}
int main() {
auto list = initial_case(123);
bool first = true;
for (auto i: list) {
if (first) {
first = false;
} else {
std::cout << ", ";
}
std::cout << i;
}
std::cout << std::endl;
}
The output is 2, 3, 3.
I want to perform the above computation and get the same output but in compile-time (the loop iteration and output-printing would be at runtime i.e. everything starting from the for loop). Templates seem like a possibility (that's why I tagged this ask as such), but I am open to anything that gets the job done in compile-time.
You can use constexpr to calculate the list at compile time. I converted the recursion to iteration and used the indices trick to call calculate as often as necessary.
#include <iostream>
#include <array>
#include <iterator>
#include <utility>
constexpr std::size_t count_digits(std::size_t N, std::size_t Count = 0)
{
return (N > 0) ? count_digits(N/10, Count+1) : Count;
}
constexpr std::size_t ipow(std::size_t N, std::size_t Base)
{
return (N > 0) ? Base*ipow(N-1,Base) : 1;
}
constexpr std::size_t calculate(std::size_t n, std::size_t i)
{
std::size_t p = ipow(i,10);
std::size_t t = (n/p) % 10;
return i > 0 ? (t+1) : t;
}
template<std::size_t Num, std::size_t C, std::size_t... Is>
constexpr std::array<std::size_t, C> build_list(std::index_sequence<Is...>)
{
return {{ calculate(Num, C-Is-1)... }};
}
template <std::size_t Num, std::size_t C = count_digits(Num)>
constexpr auto build_list()
{
return build_list<Num, C>(std::make_index_sequence<C>{});
}
int main()
{
constexpr auto list = build_list<123>();
for(auto e : list)
{
std::cout << e << " ";
}
return 0;
}
output:
2 3 3
live example
Here's one solution.
#include <iostream>
// Print one digit.
template <unsigned int N, bool Initial> struct AtomicPrinter
{
static void print()
{
std::cout << N%10;
}
};
template <unsigned int N> struct AtomicPrinter<N, false>
{
static void print()
{
std::cout << 1 + N%10 << ", ";
}
};
// Recursive printer for a number
template <unsigned int N, bool Initial> struct Printer
{
static void print()
{
Printer<N/10, false>::print();
AtomicPrinter<N, Initial>::print();
}
};
// Specialization to end recursion.
template <bool TF> struct Printer<0, TF>
{
static void print()
{
}
};
void printList()
{
Printer<123, true>::print();
std::cout << std::endl;
}
int main() {
printList();
}
If there is a need to separate printing of the digits from constructing the list of digits, you can use:
#include <iostream>
#include <list>
template <unsigned int N, bool Initial> struct Digit
{
static void get(std::list<int>& l)
{
l.push_back(N%10);
}
};
template <unsigned int N> struct Digit<N, false>
{
static void get(std::list<int>& l)
{
l.push_back(1 + N%10);
}
};
template <unsigned int N, bool Initial> struct Digits
{
static void get(std::list<int>& l)
{
Digits<N/10, false>::get(l);
Digit<N, Initial>::get(l);
}
};
template <bool TF> struct Digits<0, TF>
{
static void get(std::list<int>& l)
{
}
};
void printList()
{
std::list<int> l;
Digits<123, true>::get(l);
bool first = true;
for (auto i: l) {
if (first) {
first = false;
} else {
std::cout << ", ";
}
std::cout << i;
}
std::cout << std::endl;
}
int main() {
printList();
}
You may use something like the following to split number at compile time:
#include <utility>
#include <iostream>
template <char... Cs>
std::integer_sequence<char, Cs...> operator "" _seq() { return {}; }
template <char...Cs>
void print(std::integer_sequence<char, Cs...>)
{
const char* sep = "";
for (const auto& c : {Cs...}) {
std::cout << sep << c;
sep = ", ";
}
}
int main() {
auto seq = 123_seq;
print(seq);
}
Demo