Provide a operator== for std::variant - c++

I am trying to create an operator== operator for an std::variant defined in the map like this:
struct anyType
{
template<typename T>
void operator()(T t) const { std::cout << t; }
void operator()(const std::string& s) const { std::cout << '\"' << s << '\"'; }
};
template<typename T>
bool operator==(const std::variant<float, int, bool, std::string>& v, const& T t)
{
return v == t;
}
int main()
{
std::map<std::string, std::variant<float, int, bool, std::string>> kwargs;
kwargs["interface"] = "linear"s;
kwargs["flag"] = true;
kwargs["height"] = 5;
kwargs["length"] = 6;
//test
if (kwarg["interface"] == "linear") // stack overflow Error here
{
std::cout << true << '\n';
}
else
{
std::cout << false << '\n';
}
}
Can someone tell me why my operator isn't working?

You have a couple of issues in your code:
const &T t in your operator==, should be T const& t or const T& t.
You have forgotten to mention that you want to compare with a
std::string not with char array in your if statement(i.e. "linear"). Meaning you
need either of the followings:
if (kwargs["interface"] == std::string{ "linear" })
// or
using namespace std::string_literals;
if (kwargs["interface"] == "linear"s) // since C++14
When you do the comparison like this
if (kwargs["interface"] == "linear") // checking std::variant == char [7]
You are checking the std::variant<float, int, bool, std::string>(i.e. v) with type char [7](i.e. type of linear).
When the condition reaches the operator=='s definition you do again
the same by
return v == t; // checking std::variant == char [7]
This leads to a recursive call to the templated operator== itself
and hence stack overflow.
In order to fix, you needstrong text to explicitly specify the value from the variant either by index or by type. For example, chacking the type using std::is_same and if constexpr:
(See live online)
#include <type_traits> std::is_same_v
template<typename T>
bool operator==(const std::variant<float, int, bool, std::string>& v, T const& t)
{
if constexpr (std::is_same_v<T, float>) // float
return std::get<float>(v) == t;
else if constexpr (std::is_same_v<T, int>) // int
return std::get<int>(v) == t;
else if constexpr (std::is_same_v<T, bool>) // boolean
return std::get<bool>(v) == t;
else if constexpr (std::is_same_v<T, std::string>) // std::string
return std::get<std::string>(v) == t;
}
or simply (Credits #Barry)
template<typename T>
bool operator==(const std::variant<float, int, bool, std::string>& v, T const& t)
{
return std::get<T>(v) == t;
}
Now if you pass any other types other than v contains, you will get a compile-time error for the templated operator==.
Generic Solution!
For a generic std::varaint<Types...>, one can do as follows. In addition, it has been SFINAE d for only those types which are in the passed std::variant<Types>. I have used the is_one_of trait from this post.
(See Live Online)
#include <variant>
#include <type_traits>
// A trait to check that T is one of 'Types...'
template <typename T, typename...Types>
struct is_one_of final : std::disjunction<std::is_same<T, Types>...> {};
template<typename... Types, typename T>
auto operator==(const std::variant<Types...>& v, T const& t) noexcept
-> std::enable_if_t<is_one_of<T, Types...>::value, bool>
{
return std::get<T>(v) == t;
}

Related

aliasing a std template function

I need to alias std::get function in order to improve readability in my code.
Unfortunately I got a compile-time error get<0> in namespace ‘std’ does not name a type. using is equivalent to typedef so it needs types to work with.
I am using a std::tuple to represent some data type:
using myFoo = std::tuple<int,int,double,string>;
using getNumber = std::get<0>;
I look at some previous questions but the solution proposed is to wrap and use std::forward. I don't want to write such code for each member.
Q1 from SO
Q2 from SO
Is there a way to get around this using only using keyword?
is there a way to get around this using only using keyword?
I would say no, for std::get is not a type (thus it's not eligible for such an use).
Moreover, even if it was possible, note that std::get is an overloaded function, thus you would have been required to bind yourself to a specific implementation.
That said, in C++17, you can do something like this:
#include<tuple>
#include<utility>
using myFoo = std::tuple<int,int,double>;
constexpr auto getNumber = [](auto &&t) constexpr -> decltype(auto) { return std::get<0>(std::forward<decltype(t)>(t)); };
template<int> struct S {};
int main() {
constexpr myFoo t{0,0,0.};
S<getNumber(t)> s{};
(void)s;
}
As you can see, constexpr lambdas and variables help you creating compile-time (let me say) wrappers you can use to rename functions.
As correctly pointed out by #T.C. in the comments, if you want to generalize it even more and get an almost perfect alias for std::get, you can use a variable template:
template<int N>
constexpr auto getFromPosition = [](auto &&t) constexpr -> decltype(auto) { return std::get<N>(std::forward<decltype(t)>(t)); };
Now you can invoke it as it follows:
S<getFromPosition<0>(t)> s{};
See it on wandbox.
You can do it with a using + an enum:
#include<tuple>
using myFoo = std::tuple<int,int,double>;
int main() {
constexpr myFoo t{0,0,0.};
enum { Number = 0 };
using std::get;
auto&& x = get<Number>(t);
(void)x;
}
Although unfortunately, this is not DRY since you have to maintain an enum and a tuple simultaneously.
In my view, the most DRY and safest way to achieve this is to use tagged values in the tuple. Limit the tuple to maximum one of each tag type.
The tag is essentially a mnemonic for some unique concept:
#include <tuple>
#include <iostream>
//
// simple example of a tagged value class
//
template<class Type, class Tag>
struct tagged
{
constexpr tagged(Type t)
: value_(t) {}
operator Type&() { return value_; }
operator Type const&() const { return value_; }
Type value_;
};
struct age_tag {};
struct weight_tag {};
struct height_tag {};
using Age = tagged<int, age_tag>;
using Weight = tagged<int, weight_tag>;
using Height = tagged<double, height_tag>;
int main()
{
constexpr auto foo1 = std::make_tuple(Age(21), Weight(150), Height(165.5));
constexpr auto foo2 = std::make_tuple(Weight(150), Height(165.5), Age(21));
using std::get;
//
// note below how order now makes no difference
//
std::cout << get<Age>(foo1) << std::endl;
std::cout << get<Weight>(foo1) << std::endl;
std::cout << get<Height>(foo1) << std::endl;
std::cout << "\n";
std::cout << get<Age>(foo2) << std::endl;
std::cout << get<Weight>(foo2) << std::endl;
std::cout << get<Height>(foo2) << std::endl;
}
expected output:
21
150
165.5
21
150
165.5
In general, tuple should be used in generic code.
If you know field 1 is a Number or a Chicken, you shouldn't be using a tuple. You should be using a struct with a field called Number.
If you need tuple-like functionality (as one does), you can simply write as_tie:
struct SomeType {
int Number;
std::string Chicken;
auto as_tie() { return std::tie(Number, Chicken); }
auto as_tie() const { return std::tie(Number, Chicken); }
};
Now you can access SomeType as a tuple of references by typing someInstance.as_tie().
This still doesn't give you < or == etc for free. We can do that in one place and reuse it everywhere you use the as_tie technique:
struct as_tie_ordering {
template<class T>
using enable = std::enable_if_t< std::is_base_of<as_tie_ordering, std::decay_t<T>>, int>;
template<class T, enable<T> =0>
friend bool operator==(T const& lhs, T const& rhs) {
return lhs.as_tie() == rhs.as_tie();
}
template<class T, enable<T> =0>
friend bool operator!=(T const& lhs, T const& rhs) {
return lhs.as_tie() != rhs.as_tie();
}
template<class T, enable<T> =0>
friend bool operator<(T const& lhs, T const& rhs) {
return lhs.as_tie() < rhs.as_tie();
}
template<class T, enable<T> =0>
friend bool operator<=(T const& lhs, T const& rhs) {
return lhs.as_tie() <= rhs.as_tie();
}
template<class T, enable<T> =0>
friend bool operator>=(T const& lhs, T const& rhs) {
return lhs.as_tie() >= rhs.as_tie();
}
template<class T, enable<T> =0>
friend bool operator>(T const& lhs, T const& rhs) {
return lhs.as_tie() > rhs.as_tie();
}
};
which gives us:
struct SomeType:as_tie_ordering {
int Number;
std::string Chicken;
auto as_tie() { return std::tie(Number, Chicken); }
auto as_tie() const { return std::tie(Number, Chicken); }
};
and now
SomeTime a,b;
bool same = (a==b);
works. Note that as_tie_ordering doesn't use CRTP and is an empty stateless class; this technique uses Koenig lookup to let instances find the operators.
You can also implement an ADL-based get
struct as_tie_get {
template<class T>
using enable = std::enable_if_t< std::is_base_of<as_tie_get, std::decay_t<T>>, int>;
template<std::size_t I, class T,
enable<T> =0
>
friend decltype(auto) get( T&& t ) {
using std::get;
return get<I>( std::forward<T>(t).as_tie() );
}
};
Getting std::tuple_size to work isn't as easy, sadly.
The enable<T> =0 clauses above should be replaced with class=enable<T> in MSVC, as their compiler is not C++11 compliant.
You'll note above I use tuple; but I'm using it generically. I convert my type to a tuple, then use tuple's < to write my <. That glue code deals with tie as a generic bundle of types. That is what tuple is for.

boost::variant comparison with contained value

I am trying to find a way to compare boost::variant with underlying value without constructing variant from this underlying value. The question is defined in the comment in "main()" function
And auxiliary question is about the comparison operators defined in the code. How to decrease the # of comparison operators? If boost::variant contains, say, 6 different types, do I have to define 6! operators to be able to compare two variants?
Thanks!
#include <boost/variant.hpp>
namespace test {
namespace Tag {
struct Level1{ int t{ 1 }; };
struct Level2{ int t{ 2 }; };
}
template <typename Kind> struct Node;
using LevelOne = Node<Tag::Level1>;
using LevelTwo = Node<Tag::Level2>;
using VariantNode = boost::variant
<
boost::recursive_wrapper<LevelOne>,
boost::recursive_wrapper<LevelTwo>
>;
typedef VariantNode* pTree;
typedef std::vector<pTree> lstTree;
template <typename Kind> struct Node
{
Node(pTree p, std::string n) : parent(p), name(n) {}
Node(const Node& another) : name(another.name), parent(another.parent) {}
virtual ~Node() {}
std::string name;
pTree parent;
};
bool operator == (const LevelOne& one, const LevelTwo& two) {
return false;
}
bool operator == (const LevelTwo& two, const LevelOne& one) {
return false;
}
bool operator == (const LevelOne& one, const LevelOne& two) {
return true;
}
bool operator == (const LevelTwo& one, const LevelTwo& two) {
return true;
}
}
int main(int argc, char *argv[])
{
using namespace test;
LevelOne l1(nullptr, "level one");
VariantNode tl2 = VariantNode(LevelTwo(nullptr, "level two"));
VariantNode tl1 = VariantNode(LevelOne(nullptr, "level one"));
bool rv = (tl1 == tl2); // this line compiles OK (comparing two variants)
// comparison below does not compile, because "l1" is not a variant.
// Question: How can I compare "variant" value "tl1"
// with one of the possible content values "l1"
bool rv1 = (tl1 == l1);
return 1;
}
The following will work with any number of types in the variant:
template<typename T>
struct equality_visitor : boost::static_visitor<bool> {
explicit constexpr equality_visitor(T const& t) noexcept : t_{ &t } { }
template<typename U, std::enable_if_t<std::is_same<T, U>::value>* = nullptr>
constexpr bool operator ()(U const& u) const {
return *t_ == u;
}
template<typename U, std::enable_if_t<!std::is_same<T, U>::value>* = nullptr>
constexpr bool operator ()(U const&) const {
return false;
}
private:
T const* t_;
};
template<
typename T,
typename... Ts,
typename = std::enable_if_t<
boost::mpl::contains<typename boost::variant<Ts...>::types, T>::value
>
>
bool operator ==(T const& t, boost::variant<Ts...> const& v) {
equality_visitor<T> ev{ t };
return v.apply_visitor(ev);
}
template<
typename T,
typename... Ts,
typename = std::enable_if_t<
boost::mpl::contains<typename boost::variant<Ts...>::types, T>::value
>
>
bool operator !=(T const& t, boost::variant<Ts...> const& v) {
return !(t == v);
}
The catch is that comparisons must always be of the form value == variant or value != variant rather than variant == value or variant != value. This is because boost::variant<> itself defines these operators to always static_assert, and there is no way for us to make a global operator more specialized than variant<>'s built-in ones.
Online Demo

Pretty way to say "foo not in {bar, baz}" in C++11/14

I'm writing C++ and missing the clarity of Python. But I know that C++ has been evolving and wondering if there's a nicer way to do something like this:
if (foo != bar && foo != baz)
In Python I would do this:
if foo not in {bar, baz}:
Is there a fancy feature in C++11 or C++14 that allows me to do something similarly readable?
Edit: A lot of people are wondering why I'm trying to replace something so short. I'm not, but I didn't want to make my example as ugly and unreadable as the original code. It's more like:
if (somelongvariablename.somelongmethodname() !=
SomeReallyLongNamespace::AndAnotherSubClassname::A_LONG_CONSTANT_NAME &&
somelongvariablename.somelongmethodname() !=
SomeReallyLongNamespace::AndAnotherSubClassname::ANOTHER_LONG_CONSTANT_NAME) {
// foo
How about something like this:
#include <type_traits>
#include <tuple>
#include <utility>
template <typename ...Args> struct InT: std::tuple<Args...>
{
template <typename ...Brgs>
explicit InT(Brgs &&... brgs)
: std::tuple<Args...>(std::forward<Brgs>(brgs)...) {}
template <typename T, std::size_t ...I>
bool noteq(T && t, std::index_sequence<I...>) const
{
return (true && ... && (t != std::get<I>(*this)));
}
};
template <typename ...Args>
InT<Args &&...> AnyOf(Args &&... args)
{
return InT<Args &&...>(std::forward<Args>(args)...);
}
template <typename T, typename ...Args>
bool operator!=(T && t, InT<Args...> in)
{
return in.noteq(std::forward<T>(t), std::index_sequence_for<Args...>());
}
Usage:
if (x != AnyOf(1, 3, 5)) { f(); }
We can get this syntax:
int main() {
if (foo *in* std::tie(bar, baz)) {
}
}
live example.
It also works with C arrays or std containers or the like on the right hand side of *in*.
This should be zero overhead after the optimizer gets its teeth into it.
Negating is just:
if (!(foo *in* std::tie(bar, baz)))
as I don't think a special case is a good plan. If you want the foo *not in* std::tie(bar, baz)) syntax, see bottom of this post.
First, a named operator library:
namespace named_operator {
template<class D>struct make_operator{constexpr make_operator(){}};
template<class T, char, class O> struct half_apply { T&& lhs; };
template<class Lhs, class Op>
half_apply<Lhs, '*', Op> operator*( Lhs&& lhs, make_operator<Op> ) {
return {std::forward<Lhs>(lhs)};
}
template<class Lhs, class Op, class Rhs>
auto operator*( half_apply<Lhs, '*', Op>&& lhs, Rhs&& rhs )
-> decltype( invoke( std::declval<Lhs>(), Op{}, std::declval<Rhs>() ) )
{
return invoke( std::forward<Lhs>(lhs.lhs), Op{}, std::forward<Rhs>(rhs) );
}
}
which is about 12 lines long, and makes named operators easy.
Now we make a named operator.
namespace my_ns {
constexpr struct in_tag:named_operator::make_operator {} in {};
}
using my_ns::in;
It needs an action. The C++17 version is easy:
namespace my_ns {
// foo in tuple support:
template<class T, class...Args>
bool invoke( T const& lhs, in_tag, std::tuple<Args...> const& rhs ) {
return std::apply( [&](auto&&...args){
return (false || ... || (lhs == args));
}, rhs);
}
// foo in container support:
template<class T, class Container>
bool invoke( T const& lhs, in_tag, Container const& rhs ) {
using std::begin; using std::end;
auto it = std::find( begin(rhs), end(rhs), lhs );
return it != end(rhs);
}
}
The C++11 tuple support version is a bit trickier, because of the lack of std::apply and fold expansion:
namespace my_ns {
// tuple support:
template<class T, class...Args, std::size_t...Is>
bool invoke( T const& lhs, in_tag, std::tuple<Args...> const& rhs, std::index_sequence<Is...> ) {
bool retval = false;
using discard=int[];
(void)discard{ 0,(void(
retval = retval || (lhs == std::get<Is>(rhs))
),0)... };
return retval;
}
template<class T, class...Args>
bool invoke( T const& lhs, in_tag, std::tuple<Args...> const& rhs ) {
return invoke(lhs, in_tag{}, rhs, std::index_sequence_for<Args...>{} );
}
// container support is identical to C++17 version
}
As mentioned above, if you want
if (foo *not in* std::tie(bar, baz))
I can do it.
Add a not_in operator:
namespace my_ns {
constexpr struct not_in_tag:named_operator::make_operator<not_in_tag> {} not_in {};
}
using my_ns::not_in;
We then define ! that toggles between them:
namespace my_ns {
constexpr not_in_tag operator!(in_tag){return {};}
constexpr in_tag operator!(not_in_tag){return {};}
|
and what the not_in operator does:
namespace my_ns {
template<class T, class Rhs>
bool invoke( T const& lhs, not_in_tag, Rhs const& rhs ) {
return !invoke(lhs, in_tag{}, rhs );
}
}
for invoke.
Now we get
if (foo *not in* std::tie(bar, baz)) {
std::cout << "foo not in {bar,baz}\n";
}
if (foo *not in* std::make_tuple(bar, baz, 3)) {
std::cout << "foo not in {bar,baz, 3}\n";
}
or
if (foo *not_in* std::tie(bar, baz)) {
std::cout << "foo not in {bar,baz}\n";
}
or
if (foo *!in* std::tie(bar, baz)) {
std::cout << "foo not in {bar,baz}\n";
}
whichever you want.
live example
I strongly advise you not to pollute code with fancy stuff unless needed.
The following C++14 solution offers an infix syntax as in Python, in case you have more than two values to compare to:
#include <tuple>
#include <utility>
template <typename... T>
struct in_checker : std::tuple<T...> {
using std::tuple<T...>::tuple;
template <typename U, std::size_t... Is>
constexpr bool contains(U const& u, std::index_sequence<Is...>) const {
for (auto b : {std::get<Is>(*this) == u...})
if (b) return true;
return false;
}
template <typename U>
constexpr bool contains(U const& u) const {
return contains(u, std::index_sequence_for<T...>{});}
};
template <typename U, typename... T>
constexpr bool operator==(U const& u, in_checker<T...> const& in) {
return in.contains(u);}
template <typename U, typename... T>
constexpr bool operator!=(U const& u, in_checker<T...> const& in) {
return !(u == in);}
template <typename... T>
constexpr in_checker<T...> in(T const&... t) {return std::tie(t...);}
#include <iostream>
int main() {
int t = 2;
if (t == in(1, 2, 3))
std::cout << "Congrats";
if (t != in(1, 3, 4))
std::cout << "... again!";
}
Demo.
Not really elegant, I suppose, but you can write a simple isIn() template function
template <typename T>
bool isIn (const T & val, const std::set<T> & s)
{ return s.cend() != s.find(val); }
and the following is a simple case of use when T is int
#include <set>
#include <iostream>
template <typename T>
bool isIn (const T & val, const std::set<T> & s)
{ return s.cend() != s.find(val); }
int main ()
{
int bar = 5;
int baz = 3;
int foo = 0;
if ( false == isIn(foo, {bar, baz}) )
std::cout << foo << " isn\'t in set" << std::endl;
else
std::cout << foo << " is in set" << std::endl;
foo = 3;
if ( false == isIn(foo, {bar, baz}) )
std::cout << foo << " isn\'t in set" << std::endl;
else
std::cout << foo << " is in set" << std::endl;
return 0;
}
--- post edit edit --
#guidoism: I think your question is interesting in a more general way but, if you must only check somelongmethodname() against values of an enum, I think a readable solution could be the good old switch
using SomeReallyLongNamespace::AndAnotherSubClassname;
switch ( somelongvariablename.somelongmethodname() )
{
case A_LONG_CONSTANT_NAME:
case ANOTHER_LONG_CONSTANT_NAME:
// do nothing (or something, if you like)
break;
default:
// do something
break;
}
#include <iostream>
#include <initializer_list>
using namespace std;
template<typename T>
initializer_list<T> in(initializer_list<T> K)
{
return K;
}
template<typename T>
bool operator !=(T A, initializer_list<T> B)
{
bool R = true;
for (auto E : B)R = R && (A != E);
return R;
}
int main()
{
if (1 != in({2,3,4}))
{
cout << "Wow" << endl;
}
return 0;
}
in this way we can make the code more readable like
1 != in({2,3,4})
EDIT:
Found a more readable way.
#include <iostream>
#include <initializer_list>
using namespace std;
template<typename T>
initializer_list<T> o(initializer_list<T> K)
{
return K;
}
class not_i
{
};
class not_i_helper1
{
public:
int S;
};
not_i_helper1 operator<(int A, not_i P)
{
not_i_helper1 K;
K.S = A;
return K;
}
bool operator>(not_i_helper1 S, initializer_list<int> B)
{
bool R = true;
for (auto E : B)R = R && (S.S != E);
return R;
}
not_i not_in;
int main()
{
if (1 < not_in > o({ 2,3,4 }))
{
cout << "Success!" << endl;
}
else
{
cout << "Huh?" << endl;
}
return 0;
}
now we can use 1 < not_in > o({ 2,3,4 })
I do like the elegant simplicity of the Python syntax:
if foo not in {bar, baz}
In a scripting language minimalistic code is the highest good. But under the hood that line is going to:
Construct a simple container something like C++'s initializer_list
Insert references to bar and baz into the container
Get a reference to the 1st item in the container
Compare that reference to foo if equal destroy the container and jump to the false branch
Get the next reference in the container
Compare that reference to foo if equal destroy the container and jump to the false branch
Destroy the container and fall into the true branch
In C++ the highest good is speed so let's look at the way that we're forced to do it in C++:
if(foo != bar && foo != baz)
Compare foo to bar if equal jump to the false branch
Compare foo to baz if equal jump to the false branch
Fall through to the true branch
This is not to say that a good compiler couldn't optimize away the container in the Python if-statement, but if these variables represent objects with differing construction rules that may be all but impossible. If C++ does grace us with this syntax, I'll be the second to adopt it, right after you. But for now the construction of a temporary container to veil individual comparisons is a poor decision for 2 reasons:
1. The unintended cost of container construction may not be optimized away
2. Since there are not standard provided keywords the cost to the reader to figure out what's happening will outweigh the elegance gained by using a container
So for now the best solution is still old reliable: if(foo != bar && foo != baz)
That's not say we can't use a container in C++ though, given the type of foo, bar, and baz is int you could do either of these great evils:
if(basic_string<int>{bar, baz}.find(foo) == -1)
if(set<int>{bar, baz}.insert(foo).second)
if(!set<int>{bar, baz}.count(foo))
EDIT:
After seeing your edit to your question it should be said that even if you could use the Python syntax that only saves you: characters-in-foo + 4 characters Given the code:
if (somelongvariablename.somelongmethodname() != SomeReallyLongNamespace::AndAnotherSubClassname::A_LONG_CONSTANT_NAME &&
somelongvariablename.somelongmethodname() != SomeReallyLongNamespace::AndAnotherSubClassname::ANOTHER_LONG_CONSTANT_NAME)
If what your saying is that you have public, static variables like this:
namespace SomeReallyLongNamespace {
struct AndAnotherSubClassname{
static const auto A_LONG_CONSTANT_NAME = 13;
static const auto ANOTHER_LONG_CONSTANT_NAME = 42;
};
}
Then a using-statement will eliminate a ton of typing, not just here but everywhere within the scope that the using is defined:
using namespace SomeReallyLongNamespace;
if (somelongvariablename.somelongmethodname() != AndAnotherSubClassname::A_LONG_CONSTANT_NAME &&
somelongvariablename.somelongmethodname() != AndAnotherSubClassname::ANOTHER_LONG_CONSTANT_NAME)
Next presuming that somelongvariablename.somelongmethodname() is a const method the best practice is to mirror it's return in a constant temporary, thereby only requiring you call the method once, again improving our code:
using SomeReallyLongNamespace::AndAnotherSubClassname;
const auto& foo = somelongvariablename.somelongmethodname();
if(foo != AndAnotherSubClassname::A_LONG_CONSTANT_NAME && foo != AndAnotherSubClassname::ANOTHER_LONG_CONSTANT_NAME)
There obviously are a couple conditions there, but I'd say that if you can pull this off your concern has greatly improved your code to the point that you'd only save 7 characters with the Python syntax, returning the old faithful C++ syntax to a viable contender.
If your case is really simple you can just do this:
for (auto& e : {bar, baz})
if (foo == e)
{ /* found */ };
note, as is, this doesn't have a way to say if isn't in there.
This one is a one-liner on my 15" 16:9 laptop :D
#include <iostream>
#include <set>
int main() {
for(std::set<int> omg({1, 2, 3, 4}); omg.find(42) == omg.cend(); ) { std::cout << "There's no Answer." << std::endl; break; }
}

What is the type for dereferencing an iterator to a map or some other composite types in C++

My question is what is the type for *it, if it is of the type of std::map<std::string, int>::iterator
As a follow up to that question, if I would like to use accumulate to calculate all the map values, how could I do? Thanks.
It's a reference to an std::pair<const KeyT, ValueT> (where KeyT and ValueT are the key and value parameters of the map). You may write some kind of iterator wrapper to wrap map iterators, make them return just the value and then use std::accumulate:
template<typename ItT>
struct SecondIterator
{
ItT it;
SecondIterator(const ItT &it) : it(it) {}
SecondIterator &operator++()
{
++it;
return *this;
}
SecondIterator operator++(int)
{
SecondIterator t=*this;
++(*this);
return t;
}
SecondIterator &operator--()
{
--it;
return *this;
}
SecondIterator operator--(int)
{
SecondIterator t=*this;
--(*this);
return t;
}
typename ItT::value_type::second_type &operator*()
{
return it->second;
}
bool operator==(const SecondIterator &other)
{
return it==other.it;
}
bool operator!=(const SecondIterator &other)
{
return it!=other.it;
}
};
(probably I forgot some typename here and there, but you got the idea)
but if you ask me it's definitely not worth the effort.
If you want to accumulate the mapped_type of a std::map, perhaps the following helper classes will be of interest:
#include <functional>
#include <numeric>
#include <utility>
#ifndef USE_CXX11
#if (__cplusplus >= 201100) || (_MSC_VER >= 1800)
#define USE_CXX11 1
#endif
#endif
#if USE_CXX11
/*
map_value_accumulator - helper class that allows iterators of std::map
to be used with std::accumulate
*/
template <typename T, typename Op = std::plus<typename T::mapped_type> >
class map_value_accumulator
{
public:
typedef typename T::value_type pair_type;
typedef typename T::mapped_type value_type;
value_type operator()( value_type acc, pair_type const& p) const {
return op_( acc, p.second);
}
map_value_accumulator() : op_(Op()) {};
map_value_accumulator(Op&& op) : op_(op) {};
private:
Op op_;
};
/*
make_map_value_accumulator() - function that uses argument deduction to
help create map_value_accumulator objects
*/
// make_map_value_accumulator() that returns a user-specified operation
// the operation defaults to std::plus<> is not specified
template <typename T, typename Op = std::plus<typename T::mapped_type> >
map_value_accumulator< T, Op>
make_map_value_accumulator( T const& m, Op&& op = Op())
{
return map_value_accumulator< T, Op>(std::forward<Op>(op));
}
#else
/*
map_value_accumulator - helper class that allows iterators of std::map
to be used with std::accumulate
*/
template <typename T, typename Op = std::plus<typename T::mapped_type> >
class map_value_accumulator
{
public:
typedef typename T::value_type pair_type;
typedef typename T::mapped_type value_type;
typedef std::plus<typename T::mapped_type> default_operator_type;
value_type operator()( value_type acc, pair_type const& p) const {
return op_( acc, p.second);
}
map_value_accumulator() : op_(default_operator_type()) {};
map_value_accumulator(Op op) : op_(op) {};
private:
Op op_;
};
/*
make_map_value_accumulator() - function that uses argument deduction to
help create map_value_accumulator objects
*/
template <typename T, typename Op>
map_value_accumulator< T, Op>
make_map_value_accumulator( T const& m, Op const& op)
{
return map_value_accumulator< T, Op>(op);
}
template <typename T>
map_value_accumulator< T, std::plus<typename T::mapped_type> >
make_map_value_accumulator( T const& m)
{
typedef std::plus<typename T::mapped_type> default_operator_type;
return map_value_accumulator< T, default_operator_type>();
}
#endif /* USE_CXX11 */
#include <iostream>
#include <ostream>
#include <map>
int main()
{
std::map<char, int> m;
m.insert(std::make_pair('a', 1));
m.insert(std::make_pair('z', 26));
m.insert(std::make_pair('c', 3));
m.insert(std::make_pair('b', 2));
m.insert(std::make_pair('?', -2));
using std::cout;
using std::endl;
// directly create the map_value_accumulator functor (defaults to std::plus)
cout << accumulate(m.begin(), m.end(), 0, map_value_accumulator<std::map<char,int> >()) << endl;
// create a map_value_accumulator deduced from the user's map type (default to std::plus)
cout << accumulate(m.begin(), m.end(), 0, make_map_value_accumulator(m)) << endl;
// create a map_value_accumulator deduced from the user's map type and specifying an operation functor
cout << accumulate(m.begin(), m.end(), 1, make_map_value_accumulator(m, std::multiplies<int>())) << endl;
#if USE_CXX11
cout << "accumulate with a lambda: ";
// create a map_value_accumulator deduced from the user's map type and specifying a lambda for the operation
// (will perform a sum of squares)
cout << accumulate(m.begin(), m.end(), 0, make_map_value_accumulator(m, [](int x, int y){ return x + y * y; })) << endl;
#endif
return 0;
}
Note: I've updated the example. The first example would not work with lambdas and didn't work with MS compilers older than VS 2013. The new example has some conditional compilation that has a C++11 implementation (that supports lambdas) and a non-C++11 variant that works with VS 2003 and later and presumably any reasonable version of GCC.

generalized sorting function and using binary_function

template<class T>
struct gSorting : public std::binary_function<T, T,bool> {
bool operator() (int number, int n2)
{
cout << "int" << endl;
return (number<n2);
}
bool operator() (double number, double n2)
{
cout << "double" << endl;
return (number<n2);
}
bool operator() (const MYClass& obj1, const MYClass& obj2)
{
return (obj1.element<obj2.element);
}
};
int main () {
gSorting<int> sorting_object;
std::cout << std::boolalpha << sorting_object (2.0f, 4.3f) << ".\n";
std::getchar();
return 0;
}
is there any problem with this code? is it that generic? or is there better way to do a generic sorting algorithm to include all of my classes used
it compiles, the output pointed to the double which is good, however how can I make it a template, but dont have to specify the input type in the declaration?
gSorting< int > sorting_object;
-------------^^^^ we dont need any specific type? am I right
output:
I would personally define a class template for the binary predicate and specialize it as needed, e.g.:
template <typename T>
struct gSorting
: std::binary_function<T const&, T const&, bool> // not really needed
{
bool operator()(T const& t0, T const& t1) const {
return t0 < t1;
}
};
template <>
struct gSorting<MyClass>
: std::binary_function<MyClass const&, MyClass const&, bool>
{
bool operator()(MyClass const& c0, MyClass const& c1) const {
return c0.element < c1.element;
}
};
In a real implementation, the argument type for the generic version should probably decide whether the argument is passed by value or by const& depending on the kind of type and/or based on a trait which is then specialized as needed. For example:
template <typename T>
struct argument_type
{
typedef typename std::conditional<
std::is_fundamental<T>::value, T, T const&>::type type;
};
template <typename T>
struct gSorting
: std::binary_function<typename argument_type<T>::type,
typename argument_type<T>::type, bool>
{
typedef typename argument_type<T>::type arg_type;
bool operator()(arg_type t0, arg_type t1) const {
return t0 < t1;
}
};