I was trying to implement a n-tuple from scratch starting with the mathematical base ordered-pair
where n-tuple (a,b,c) = ordered_pair(a,ordered_pair(b,c)) and ordered pair is a set representation
ie. ordered_pair(a,b) = set{{a},{a,b}}
here is the code for ordered_pair
#include <iostream>
#include <set>
#include <boost/variant.hpp>
using namespace std;
template <typename T, typename U, typename Z>
class orderd_pair{
//typedef boost::variant<int,std::string,double> cell;
private:
set<set<Z>> opair;
set<T> first;
set<U> second;
public:
set<set<Z>> Orderd_pair(T first_element, U second_element){
first.insert(first_element);
second.insert(first_element);
second.insert(second_element);
opair.insert(first);
opair.insert(second);
return opair;
}
//TO DO void print_elements(std::set<std::set<cell>> opair);*/
};
the problem is when trying to implement tuple set of each ordered_pair must be nested ie
for three element tuple set{{a},{a,{{b},{b,c}}}} and for more elements it will be nested even more making it hard to work with, how can I solve this??
also I have used boost::variant to support int,std::string and double data types.
You will quickly find that you can't put a std::set<T> into the same container as a std::set<U> if T is different to U. So you are likely to end up with
struct any_less {
bool operator()(const std::any & lhs, const std::any & rhs) {
return type_index(lhs.type()) < type_index(rhs.type());
}
}
using ordered_pair = std::set<std::set<std::any, any_less>>;
Codifying your recurrence relation.
template <typename A, typename B>
ordered_pair make_ordered_pair(A a, B b) {
return { { a }, { a, b } };
}
template <typename A, typename B, typename C, typename... Rest>
ordered_pair make_ordered_pair(A a, B b, C c, Rest... rest) {
return { { a }, { a, make_ordered_pair(b, c, rest...) } };
}
But C++ has a much better type for ordered pairs: std::pair. It also has a much better type for tuples: std::tuple.
Related
At work, I ran into a situation where the best type to describe the result returned from a function would be std::variant<uint64_t, uint64_t> - of course, this isn't valid C++, because you can't have two variants of the same type. I could represent this as a std::pair<bool, uint64_t>, or where the first element of the pair is an enum, but this is a special case; a std::variant<uint64_t, uint64_t, bool> isn't so neatly representable, and my functional programming background really made me want Either - so I went to try to implement it, using the Visitor pattern as I have been able to do in other languages without native support for sum types:
template <typename A, typename B, typename C>
class EitherVisitor {
virtual C onLeft(const A& left) = 0;
virtual C onRight(const B& right) = 0;
};
template <typename A, typename B>
class Either {
template <typename C>
virtual C Accept(EitherVisitor<A, B, C> visitor) = 0;
};
template <typename A, typename B>
class Left: Either<A, B> {
private:
A value;
public:
Left(const A& valueIn): value(valueIn) {}
template <typename C>
virtual C Accept(EitherVisitor<A, B, C> visitor) {
return visitor.onLeft(value);
}
};
template <typename A, typename B>
class Right: Either<A, B> {
private:
B value;
public:
Right(const B& valueIn): value(valueIn) {}
template <typename C>
virtual C Accept(EitherVisitor<A, B, C> visitor) {
return visitor.onRight(value);
}
};
C++ rejects this, because the template method Accept cannot be virtual. Is there a workaround to this limitation, that would allow me to correctly represent the fundamental sum type in terms of its f-algebra and catamorphism?
Perhaps the simplest solution is a lightweight wrapper around T for Right and Left?
Basically a strong type alias (could also use Boost's strong typedef)
template<class T>
struct Left
{
T val;
};
template<class T>
struct Right
{
T val;
};
And then we can distinguish between them for visitation:
template<class T, class U>
using Either = std::variant<Left<T>, Right<U>>;
Either<int, int> TrySomething()
{
if (rand() % 2 == 0) // get off my case about rand(), I know it's bad
return Left<int>{0};
else
return Right<int>{0};
}
struct visitor
{
template<class T>
void operator()(const Left<T>& val_wrapper)
{
std::cout << "Success! Value is: " << val_wrapper.val << std::endl;
}
template<class T>
void operator()(const Right<T>& val_wrapper)
{
std::cout << "Failure! Value is: " << val_wrapper.val << std::endl;
}
};
int main()
{
visitor v;
for (size_t i = 0; i < 10; ++i)
{
auto res = TrySomething();
std::visit(v, res);
}
}
Demo
std::variant<X,X> is valid C++.
It is a bit awkward to use, because std::visit doesn't give you the index, and std::get<X> won't work either.
The way you can work around this is to create a variant-of-indexes, which is like a strong enum.
template<std::size_t i>
using index_t = std::integral_constant<std::size_t, i>;
template<std::size_t i>
constexpr index_t<i> index = {};
template<std::size_t...Is>
using number = std::variant< index_t<Is>... >;
namespace helpers {
template<class X>
struct number_helper;
template<std::size_t...Is>
struct number_helper<std::index_sequence<Is...>> {
using type=number<Is...>;
};
}
template<std::size_t N>
using alternative = typename helpers::number_helper<std::make_index_sequence<N>>::type;
we can then extract the alternative from a variant:
namespace helpers {
template<class...Ts, std::size_t...Is, class R=alternative<sizeof...(Ts)>>
constexpr R get_alternative( std::variant<Ts...> const& v, std::index_sequence<Is...> ) {
constexpr R retvals[] = {
R(index<Is>)...
};
return retvals[v.index()];
}
}
template<class...Ts>
constexpr alternative<sizeof...(Ts)> get_alternative( std::variant<Ts...> const& v )
{
return helpers::get_alternative(v, std::make_index_sequence<sizeof...(Ts)>{});
}
so now you have a std::variant<int, int>, you can
auto which = get_alternative( var );
and which is a variant, represented at runtime by an integer which is the index of the active type in var. You can:
std::variant<int, int> var( std::in_place_index_t<1>{}, 7 );
auto which = get_alternative( var );
std::visit( [&var](auto I) {
std::cout << std::get<I>(var) << "\n";
}, get_alternative(var) );
and get access to which of the alternative possibilities in var is active with a compile time constant.
The get_alternative(variant), I find, makes variant<X,X,X> much more usable, and fills in the hole I think you might be running into.
Live example.
Now if you don't need a compile-time index of which one is active, you can just call var.index(), and visit via visit( lambda, var ).
When you construct the variant, you do need the compile time index to do a variant<int, int> var( std::in_place_index_t<0>{}, 7 ). The wording is a bit awkward, because while C++ supports variants of multiples of the same type, it considers them a bit less likely than a "standard" disjoint variant outside of generic code.
But I've used this alternative and get_alternative like code to support functional programming like data glue code before.
Extremely new to c++ however have a question regarding templates
Suppose I have a simple template class as defined below:
template<typename Collection>
class MySack {
private:
Collection c;
public:
typedef typename Collection::value_type value_type;
void add(const value_type& value) {
c.push_back(value);
}
};
The aim of the class being to accept any type of collection, and allow a user to insert the correct type of value for the specified typename Collection.
The obvious problem is that this is only going to work for types which have a push_back method defined, which means it would work with list however not with set.
I started reading about template specialization to see if that'd be any help, however I don't think this would provide a solution as the type contained within the set would have to be known.
How would this problem be approached in c++?
You can use std::experimental::is_detected and if constexpr to make it work:
template<class C, class V>
using has_push_back_impl = decltype(std::declval<C>().push_back(std::declval<V>()));
template<class C, class V>
constexpr bool has_push_back = std::experimental::is_detected_v<has_push_back_impl, C, V>;
template<typename Collection>
class MySack {
private:
Collection c;
public:
typedef typename Collection::value_type value_type;
void add(const value_type& value) {
if constexpr (has_push_back<Collection, value_type>) {
std::cout << "push_back.\n";
c.push_back(value);
} else {
std::cout << "insert.\n";
c.insert(value);
}
}
};
int main() {
MySack<std::set<int>> f;
f.add(23);
MySack<std::vector<int>> g;
g.add(23);
}
You can switch to insert member function, which has the same syntax for std::vector, std::set, std::list, and other containers:
void add(const value_type& value) {
c.insert(c.end(), value);
}
In C++11, you might also want to create a version for rvalue arguments:
void add(value_type&& value) {
c.insert(c.end(), std::move(value));
}
And, kind-of simulate emplace semantics (not truly in fact):
template <typename... Ts>
void emplace(Ts&&... vs) {
c.insert(c.end(), value_type(std::forward<Ts>(vs)...));
}
...
int main() {
using value_type = std::pair<int, std::string>;
MySack<std::vector<value_type>> v;
v.emplace(1, "first");
MySack<std::set<value_type>> s;
s.emplace(2, "second");
MySack<std::list<value_type>> l;
l.emplace(3, "third");
}
I started reading about template specialization to see if that'd be
any help, however I don't think this would provide a solution as the
type contained within the set would have to be known.
You can partially specialize MySack to work with std::set.
template <class T>
class MySack<std::set<T>> {
//...
};
However, this has the disadvantage that the partial specialization replaces the whole class definition, so you need to define all member variables and functions again.
A more flexible approach is to use policy-based design. Here, you add a template parameter that wraps the container-specific operations. You can provide a default for the most common cases, but users can provide their own policy for other cases.
template <class C, class V = typename C::value_type>
struct ContainerPolicy
{
static void push(C& container, const V& value) {
c.push_back(value);
}
static void pop(C& container) {
c.pop_back();
}
};
template <class C, class P = ContainerPolicy<C>>
class MySack
{
Collection c;
public:
typedef typename Collection::value_type value_type;
void add(const value_type& value) {
P::push(c, value);
}
};
In this case, it is easier to provide a partial template specialization for the default policy, because it contains only the functionality related to the specific container that is used. Other logic can still be captured in the MySack class template without the need for duplicating code.
Now, you can use MySack also with your own or third party containers that do not adhere to the STL style. You simply provide your own policy.
struct MyContainer {
void Add(int value);
//...
};
struct MyPolicy {
static void push(MyContainer& c, int value) {
c.Add(value);
}
};
MySack<MyContainer, MyPolicy> sack;
If you can use at least C++11, I suggest the creation of a template recursive struct
template <std::size_t N>
struct tag : public tag<N-1U>
{ };
template <>
struct tag<0U>
{ };
to manage precedence in case a container can support more than one adding functions.
So you can add, in the private section of your class, the following template helper functions
template <typename D, typename T>
auto addHelper (T && t, tag<2> const &)
-> decltype((void)std::declval<D>().push_back(std::forward<T>(t)))
{ c.push_back(std::forward<T>(t)); }
template <typename D, typename T>
auto addHelper (T && t, tag<1> const &)
-> decltype((void)std::declval<D>().insert(std::forward<T>(t)))
{ c.insert(std::forward<T>(t)); }
template <typename D, typename T>
auto addHelper (T && t, tag<0> const &)
-> decltype((void)std::declval<D>().push_front(std::forward<T>(t)))
{ c.push_front(std::forward<T>(t)); }
Observe that the decltype() part enable they (through SFINAE) only if the corresponding method (push_back(), insert() or push_front()) is enabled.
Now you can write add(), in the public section, as follows
template <typename T>
void add (T && t)
{ addHelper<C>(std::forward<T>(t), tag<2>{}); }
The tag<2> element make so the tag<2> addHelper() method is called, if available (if push_back() is available for type C), otherwise is called the tag<1> method (the insert() one) if available, otherwise the tag<0> method (the push_front() one) is available. Otherwise error.
Also observe the T && t and std::forward<T>(t) part. This way you should select the correct semantic: copy or move.
The following is a full working example
#include <map>
#include <set>
#include <list>
#include <deque>
#include <vector>
#include <iostream>
#include <forward_list>
#include <unordered_map>
#include <unordered_set>
template <std::size_t N>
struct tag : public tag<N-1U>
{ };
template <>
struct tag<0U>
{ };
template <typename C>
class MySack
{
private:
C c;
template <typename D, typename T>
auto addHelper (T && t, tag<2> const &)
-> decltype((void)std::declval<D>().push_back(std::forward<T>(t)))
{ c.push_back(std::forward<T>(t)); }
template <typename D, typename T>
auto addHelper (T && t, tag<1> const &)
-> decltype((void)std::declval<D>().insert(std::forward<T>(t)))
{ c.insert(std::forward<T>(t)); }
template <typename D, typename T>
auto addHelper (T && t, tag<0> const &)
-> decltype((void)std::declval<D>().push_front(std::forward<T>(t)))
{ c.push_front(std::forward<T>(t)); }
public:
template <typename T>
void add (T && t)
{ addHelper<C>(std::forward<T>(t), tag<2>{}); }
};
int main ()
{
MySack<std::vector<int>> ms0;
MySack<std::deque<int>> ms1;
MySack<std::set<int>> ms2;
MySack<std::multiset<int>> ms3;
MySack<std::unordered_set<int>> ms4;
MySack<std::unordered_multiset<int>> ms5;
MySack<std::list<int>> ms6;
MySack<std::forward_list<int>> ms7;
MySack<std::map<int, long>> ms8;
MySack<std::multimap<int, long>> ms9;
MySack<std::unordered_map<int, long>> msA;
MySack<std::unordered_multimap<int, long>> msB;
ms0.add(0);
ms1.add(0);
ms2.add(0);
ms3.add(0);
ms4.add(0);
ms5.add(0);
ms6.add(0);
ms7.add(0);
ms8.add(std::make_pair(0, 0L));
ms9.add(std::make_pair(0, 0L));
msA.add(std::make_pair(0, 0L));
msB.add(std::make_pair(0, 0L));
}
Are there constexpr or other compile time equivalents to the STL functional and other libraries for use with metaprogramming? More specifically, I am trying to write some metaprograms that use SFINAE to evaluate some conditional and generate the corresponding types. Example:
template<int A, int B>
enable_if_t<(A < B)> my_func() {// do something
}
template<int A, int B>
enable_if_t<!(A < B)> my_func() {// do nothing
}
Ideally I would like the user to be able to pass in a comparator (like std::less<int>), rather than hard coding it to <. So something like:
template<int A, int B, class comp = std::less<int>>
enable_if_t<comp(A, B)> my_func() {// do something
}
template<int A, int B, class comp = std::less<int>>
enable_if_t<comp(A, B)> my_func() {// do nothing
}
However since the functional objects are not constant expressions, they are not getting evaluated at compile time and so this does not work. What would be the right way to implement something like this?
std::less<int>(int, int) is not a constructor for std::less. The only constructor for std::less is () (I prefer using {}, because it makes it clear I'm constructing something).
Since C++14 it has a constexpr operator() that (if < on the types involved is constexpr) can be evaluated at compile time.
Thus:
template<int A, int B, class comp = std::less<int>>
enable_if_t<comp{}(A, B)> my_func() {// do something
}
template<int A, int B, class comp = std::less<int>>
enable_if_t<!comp{}(A, B)> my_func() {// do nothing
}
should work.
In C++11
namespace notstd {
template<class T=void>
struct less {
constexpr bool operator()(T const& lhs, T const& rhs)const{
return lhs<rhs;
}
};
template<>
struct less<void> {
template<class T, class U>
constexpr bool operator()(T const& lhs, U const& rhs)const{
return lhs<rhs;
}
// maybe also add this:
//struct is_transparent {};
}
}
(assuming your < on your system is a total order on pointers) should work (replacing std::less<T> with notstd::less<T>).
Is it possible to call std::sort() on a std::vector of objects in such a way that we can specify which member will be used to compare the objects, but without having to implement a seperate compare function for each member. We can assume that each member that we want to sort by will have the < operator defined. If not, what is the best approach when we want to be able to sort a container of objects by many different criteria.
You can have a comparison object that has a flag indicating which member to sort on.
class Comparo
{
int m_field;
public:
Comparo(int field) : m_field(field) { }
bool operator()(const MyClass & Left, const MyClass & right)
{
switch (m_field)
{
case 0:
return left.A < right.A;
case 1:
return left.B < right.B;
}
}
};
std::vector<MyClass> vec = FillMyVector();
std::sort(vec.begin(), vec.end(), Comparo(0)); // sorts on field A
std::sort(vec.begin(), vec.end(), Comparo(1)); // sorts on field B
Here's something that does a lexicographical comparison using arbitrarily many members of any class. Needs C++14 for variadic templates and compile-time integer sequences. You can implement compile-time integer sequences yourself if you have C++11.
#include <tuple>
#include <utility> // for make_index_sequence
template<class T, typename... types>
struct member_comparer {
member_comparer(types T::*... args) : ptrs(args...) { }
bool operator()(const T& t1, const T& t2) const {
return do_compare(t1, t2, std::make_index_sequence<sizeof...(types)>());
}
private:
template<size_t... indices>
bool do_compare(const T& t1, const T& t2, std::index_sequence<indices...> ) const {
return std::tie(t1.*std::get<indices>(ptrs)...) <
std::tie(t2.*std::get<indices>(ptrs)...);
}
std::tuple<types T::* ...> ptrs;
};
template<class T, typename... types>
auto make_member_comparer(types T::*... args) {
return member_comparer<T, types...>(args...);
}
You use it like:
struct A {
int x;
double y;
float z;
};
auto compare_x_only = make_member_comparer(&A::x);
auto compare_y_then_x = make_member_comparer(&A::y, &A::x);
Demo.
Is it possible to iterate over all elements in a struct or class?
For example if I have a struct of three elements of different type:
struct A {
classA a;
classB b;
classC c;
};
then I need some iterator such that a method next() would give me the value
of the next element. The problem is that as you see, the values have different types.
Nope, not with the language as it is.
You could do it by deriving your classes from a common base, and then implementing your own iterator to return pointers to each item as the iterator is traversed.
Alternatively put the items in a std::vector and use that to provide the iteration.
No, there is no reflection in C++, (yet, there are murmurs about static reflection coming one day).
Anyway, there is a way to work around this, to an extent - first of all, you'll need a (temporary) tuple with references to your data members.
Then you will need a construct "iterating" over the tuple, such as:
void applyToAll() { }
template <typename Lambda, typename... Lambdas>
void applyToAll(Lambda&& closure, Lambdas&&... closures) {
std::forward<Lambda>(closure)();
applyToAll(std::forward<Lambdas>(closures)...);
}
// use your favourite sequence-making trick
template <unsigned... Is>
struct _Sequence {
typedef _Sequence<Is...> type;
};
template <unsigned Max, unsigned... Is>
struct _MakeSequence : _MakeSequence<Max - 1, Max - 1, Is...> { };
template <unsigned... Is>
struct _MakeSequence<0, Is...> : _Sequence<Is...> { };
template <typename Tuple, typename Functor, unsigned... Is>
void _foreachElemInTuple(_Sequence<Is...>, Tuple&& t, Functor&& f) {
applyToAll(
[&]{ std::forward<Functor>(f)(std::get<Is>(std::forward<Tuple>(t))); }...
);
}
template <typename Tuple, typename Functor>
void foreachElemInTuple(Tuple&& t, Functor&& f) {
_foreachElemInTuple(
_MakeSequence<std::tuple_size<
typename std::decay<Tuple>::type>::value>(),
std::forward<Tuple>(t), std::forward<Functor>(f)
);
}
Then you can call foreachElemInTuple(yourTuple, some_adapter()).
Your adapter will look like:
struct some_adapter {
template <typename... Args>
// A little bit of C++14, you can also just -> decltype the thing
decltype(auto) operator()(Args&& ... args) const {
return doStuff(std::forward<Args>(args)...);
}
};
As everyone else says, you cannot directly iterate over data members of a
class. However, it is not difficult to do it indirectly, provided of course that
you can access each of the data members you want to iterate over. The idea
in essense, as per ScarletAmaranth's solution, is to iterate over an std::tuple
of references to those data members.
The following program shows how to obtain such a tuple, using std::forward_as_tuple,
and another way to do the iterating by compiletime recursion, without
auxiliary apparatus.
#include <tuple>
/* You want to be able do something with the values of the members of an `A`
in turn.
*/
struct A
{
char ch;
int i;
double d;
// May also have members of class type. It doesn't matter
};
/* 1) Provide yourself with the means of creating a sequence that contains
references to the data members of a given `A`
*/
std::tuple<char const &, int const &, double const &> get_A_vals(A const & a)
{
return std::forward_as_tuple(a.ch,a.i,a.d);
}
/* 2) Provide yourself with a means of applying some operation, `Func`,
to each element of an `std::tuple`
*/
template<size_t I = 0, typename Func, typename ...Ts>
typename std::enable_if<I == sizeof...(Ts)>::type
for_each_in_tuple(std::tuple<Ts...> const &, Func) {}
template<size_t I = 0, typename Func, typename ...Ts>
typename std::enable_if<I < sizeof...(Ts)>::type
for_each_in_tuple(std::tuple<Ts...> const & tpl, Func func)
{
func(std::get<I>(tpl));
for_each_in_tuple<I + 1>(tpl,func);
}
/* 3) Combine 1) and 2) to apply `Func` over the members of an `A`
*/
template<typename Func>
void for_each_in_A(A const & a, Func func)
{
for_each_in_tuple(get_A_vals(a),func);
}
// Testing...
#include <iostream>
// A specimen operation: just prints its argument
struct printer
{
template<typename T>
void operator () (T && t)
{
std::cout << t << std::endl;
}
};
int main()
{
A a{'a',1,2.0};
for_each_in_A(a,printer());
return 0;
}
// EOF
The program outputs:
a
1
2
If you have control of the structs or classes over whose members you need to
iterate, you may consider whether it is practical simply to dispense with them
and use the corresponding std::tuples everywhere.
Code built with gcc 4.8.2 and clang 3.3, -std=c++11.