C++ STL functional equivalents for metaprogramming - c++

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>).

Related

Sum types in C++

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.

C++ std::set metaprograming set of set of set ... nesting

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.

Comparing 2 values using template metaprogramming C++

I want to have a default function as a "Predicate" template in case the user doesn't provide one. So far I've been doing something like:
template<typename T>
struct simple_compare{
bool operator()(T const& a, T const& b){
return a > b;
}
};
template<typename T, typename Predicate=simple_compare<T> >
bool compare(T a, T b, Predicate pred) {
return pred(a, b);
}
Can this be done using template metaprogramming in C++ instead of having a struct with an overloaded () operator?
There is no need for template metaprogramming here. You can simply use overloading like shown in the answer by Davide Spataro to provide a version that doesn't take a predicate and just calls the full version with a default predicate. Or you can just use a default argument for your predicate:
template <typename T, typename Predicate = simple_compare<T>>
bool compare(T a, T b, Predicate pred = {}) {
return pred(a, b);
}
If you just want a generic functor that invokes the > operator, then you could also just make the operator () a template instead of the functor type itself and let the exact types to compare be deduced from the call:
struct simple_compare {
template <typename A, typename B>
bool operator()(A const& a, B const& b) const {
return a > b;
}
};
template <typename T, typename Predicate = simple_compare>
bool compare(T a, T b, Predicate pred = {}) {
return pred(a, b);
}
Also, the standard library already provides standard functors for invoking all sorts of operators. So instead of rolling your own, you could just use std::greater<T> or std::greater<void> in your example. Furthermore, I assume there is no real need to require your arguments to be copyable and of the same type:
template <typename A, typename B, typename Predicate = std::greater<void>>
bool compare(A const& a, B const& b, Predicate pred = {}) {
return pred(a, b);
}
You do not need fancy template metaprogramming things.
Simply create two versions of the template function. The one without the custom predicate will simply execute the default one.
Something as the following should works:
auto default_pred = [](const auto a, const auto b) {return a > b;};
auto custom_pred = [](const auto a, const auto b) {return a < b;};
template<typename T, typename Fn >
bool compare2(T a, T b, Fn pred) {
return pred(a, b);
}
template<typename T >
bool compare2(T a, T b) {
return default_pred (a, b);
}
int main(){
cout<<compare2(2, 4)<<endl;
cout<<compare2(10.2d, 4.5d, custom_pred)<<endl;
return 0;
}

Metaprogramming C++, max between two templates parameters

I haven't been doing this for a while. I basically have a class
template <int L>
class MyInteger {
//code
};
And specifically I'd like to implement something like (as a method)
template <int L, int M, int N>
MyInteger<N> MyInteger<L>::operator+(const MyInteger<M>& x) const;
But I want to restrict N to be the max(L,M) is there a way to achieve that using template metaprogramming? I was thinking the use of enable_if and maybe SFINAE could allow me to achieve what I want, but I'm not entirely sure how to do that.
Do you just want it to be the max of the two? Or do you want it to be no more than the max of the two? If you want it to always be the max I'd create a utility struct like below and set N as
template<int L,int M>
struct MaxInteger
{
public:
static const int value = L > M ? L : M;
};
Then implement it like this.
template<int L, int M>
MyInteger<MaxInteger<L,M>::value> MyInteger<L>::operator+(const MyInteger<M>& x) const;
Edit: As requested a constexpr implementation.
constexpr int constMax(constexpr int a,constexpr int b) {return a > b ? a : b;}
Then implement like this
template<int L, int M>
MyInteger<constMax(L,M)> MyInteger<L>::operator+(const MyInteger<M>& x) const;
or you can do it without the struct
template<int L, int M>
MyInteger<L > M ? L : M> MyInteger<L>::operator+(const MyInteger<M>& x) const;
In C++14 (as you tagged the question) you can simply do this:
#include <type_traits>
template <int L>
class MyInteger {};
template <int L, int M>
constexpr auto operator+(const MyInteger<L> &lhs, const MyInteger<M> &rhs) {
return MyInteger<(L > M ? L : M)>{};
}
int main() {
constexpr MyInteger<0> m1;
constexpr MyInteger<1> m2;
static_assert(std::is_same<decltype(m1 + m2), MyInteger<1>>::value, "!");
}
That is, use the auto return type and let the compiler deduce it for you.
Then, in the body of the function, you can pick the max value up and create the right type.
If you prefer to be explicit about the return type, another possible solution is this:
template <int L, int M>
constexpr MyInteger<(L > M ? L : M)> operator+(const MyInteger<L> &lhs, const MyInteger<M> &rhs) {
return {};
}
No need to use sfinae anywhere.

c++ std::sort() a vector of objects by any comparable member using only one compare function

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.