Achieve functor overloading through composition - c++

Given some existing functors:
struct incr {
int operator()(int x) const { return x + 1; }
};
struct rep_str {
std::string operator()(const std::string& s) const { return s + s; }
};
I'm wondering if it's possible to achieve something like this:
auto f = overload<incr, rep_str>();
f(1); // returns 2
f("hello"); // returns "hellohello"
Multiple overloads may look like:
auto f = overload<fa, fb, fc, ...>();
// or...
auto g = overload<fa, overload<fb, overload<fc, ...>>>();
I'm thinking maybe use SFINAE with std::result_of_t or something like that, but haven't figured out how.

You don't need anything too fancy: just inherit from all the arguments and use using-declarations to bring in operator() from the base classes. However, in the variadic case, you can't have a pack expansion in a using-declaration, so you have to use a recursive approach, like so:
template <class... Ts>
struct overload {}; // only used for empty pack
template <class T>
struct overload<T> : private T {
using T::operator();
};
template <class T1, class T2, class... Ts>
struct overload<T1, T2, Ts...> : private T1, overload<T2, Ts...> {
using T1::operator();
using overload<T2, Ts...>::operator();
};

Brian's answer is better, IMHO, but since I worked on it, here's mine:
#include <type_traits>
#include <utility>
template <typename... Fns>
struct overload;
template <typename Fn, typename... Fns>
struct overload<Fn, Fns...>
{
template <typename... T>
std::result_of_t<Fn(T...)> operator()(T && ... args) const {
return Fn()(std::forward<T>(args)...);
}
using next = overload<Fns...>;
template <typename... T>
std::result_of_t<next(T...)> operator()(T && ... args) const {
return next()(std::forward<T>(args)...);
}
};

this can be done using template specialization:
#include <string>
#include <iostream>
template <typename...Args>
struct overload{
};
template <> struct overload<int>{
int operator()(int x) const { return x + 1; }
};
template <> struct overload< std::string>{
std::string operator()(const std::string& s) const { return s + s; }
};
template <typename...Args >
auto f(Args...arg){
overload<Args...> func;
return func(arg...);
}
int main()
{
std::cout << f(3) << std::endl << f(std::string("Hello"));
}
Note: two answers by #Brian and #md5i more general and elegant and perfect and better than this.

Related

variadic arguments which are all a specialization of a template type

We can validate at compile time that an input to a function is a specialization of a template. I.E the following code validates that the input for f is some specialization of struct Holder.
template<typename T>
struct Holder<T> {...};
template<typename T>
void f(Holder<T> h) {...};
I want to validate that a set of variadic arguments are a specialization of a template.
More precisely I want to differentiate between two consecutive sets of variadic arguments - a set which is a specialization of a template, and a set which isn't.
Following is an example of how it might have looked like if the syntax allowed it to -
template<...Args1, ...Args2>
void f(Holder<Args1>.... args_which_are_specializations_of_Holder, Args2... args_which_are_not) {
use_holders(args_which_are_specializations_of_Holder...);
use_rest(args_which_are_not...);
return;
}
Is this possible ?
Thanks,
You can store the args in a tuple and calculate the index of the last Holder argument, then extract the Holder and normal arguments by index and forward them to the corresponding function.
#include <tuple>
template<class T>
constexpr bool is_holder = false;
template<class T>
constexpr bool is_holder<Holder<T>> = true;
template<class... Args>
void f(Args... args) {
constexpr auto holder_index = (is_holder<Args> + ... + 0);
auto args_tuple = std::tuple(args...);
[&args_tuple]<auto... Is>(std::index_sequence<Is...>) {
use_holders(std::get<Is>(args_tuple)...);
}(std::make_index_sequence<holder_index>{});
[&args_tuple]<auto... Is>(std::index_sequence<Is...>) {
use_rest(std::get<Is + holder_index>(args_tuple)...);
}(std::make_index_sequence<sizeof...(Args) - holder_index>{});
}
Demo
It's harder to mix variadic arguments like that. You can use std::tuple:
#include <tuple>
#include <cstdio>
template<class T>
struct Holder {
T value;
};
template <class ...T1, class ...T2>
void f(const std::tuple<Holder<T1>...>& holders, const std::tuple<T2...>& non_holders) {
std::printf("Holder count: %zu\n"
"Non-holder count: %zu\n", sizeof...(T1), sizeof...(T1));
}
int main() {
Holder<int> a{};
Holder<double> b{};
int c{};
double d{};
f(std::tuple{a, b}, std::tuple{c, d});
}

SFINAE | strange behaviour

I am studying SFINAE and c++ in general. I'm having a strange behaviour with My SFINAE macros (called here "annotations"):
<lang/Annotations.h>
#pragma once
#define ENABLE_IF(y) typename std::enable_if<y,std::nullptr_t>::type
#define IS_REFERENCE(x) std::is_reference<x>::value
#define IS_CONSTRUCTIBLE(...) std::is_constructible<__VA_ARGS__>::value
I made a custom "MY_OBJECT" class, which provides the following constructor:
MY_OBJECT(const char* stringDataPtr) noexcept;
The objective here is the following:
By using a variadic template function, each template argument's type must be checked: if it can be passed to String constructor (std::is_constructible) then a message "is constructible" must be printed, otherwise "is not constructible" must be printed.
The problem
Even by passing int values, my SFINAE method does not get "SFINAE'd" and I always get "Is constructible" message.
<util/SFINAETools.h
namespace SFINAETools {
enum class SFINAEResult {
IS_CONSTRUCTIBLE,
IS_NOT_CONSTRUCTIBLE,
IS_REFERENCE,
IS_NOT_REFERENCE
};
std::ostream& operator<<(std::ostream& out, const SFINAEResult& value) {
static std::unordered_map<SFINAEResult, System::MyString> strings {
{SFINAEResult::IS_CONSTRUCTIBLE, "IS_CONSTRUCTIBLE"},
{SFINAEResult::IS_NOT_CONSTRUCTIBLE, "IS_NOT_CONSTRUCTIBLE"},
{SFINAEResult::IS_REFERENCE, "IS_REFERENCE"},
{SFINAEResult::IS_NOT_REFERENCE, "IS_NOT_REFERENCE"}
};
return out << strings[value];
}
class SFINAECallbackHandler : public Object {
public:
virtual void onSFINAEResult(const SFINAEResult& result) const = 0;
};
template <typename... ARGS, ENABLE_IF(IS_CONSTRUCTIBLE(ARGS...))>
void executeIfConstructible(const SFINAECallbackHandler& callBackHandler) {
callBackHandler.onSFINAEResult(SFINAEResult::IS_CONSTRUCTIBLE);
}
template <typename... ARGS, ENABLE_IF(!IS_CONSTRUCTIBLE(ARGS...))>
void executeIfConstructible(const SFINAECallbackHandler& callBackHandler) {
callBackHandler.onSFINAEResult(SFINAEResult::IS_NOT_CONSTRUCTIBLE);
}
template <typename X, ENABLE_IF(IS_REFERENCE(X))>
void executeIfIsReference(const SFINAECallbackHandler& callBackHandler) {
callBackHandler.onSFINAEResult(SFINAEResult::IS_REFERENCE);
}
template <typename X, ENABLE_IF(!IS_REFERENCE(X))>
void executeIfIsReference(const SFINAECallbackHandler& callBackHandler) {
callBackHandler.onSFINAEResult(SFINAEResult::IS_NOT_REFERENCE);
}
};
MAIN.cpp
#include <lang/CppApplication.h>
#include <util/SFINAETools.h>
class MyCallbackHandler :public SFINAETools::SFINAECallbackHandler {
public:
virtual void onSFINAEResult(const SFINAETools::SFINAEResult& result) const override {
std::cout << result << std::endl;
}
};
class MY_OBJECT : public Object {
public:
MY_OBJECT(const char* strDataPtr) {
}
};
class Main : public CppApplication {
public:
virtual int main(const std::vector<String>& arguments) override {
createString(1, "2");
return 0;
}
template <typename Arg1>
void createString(Arg1&& arg1) {
SFINAETools::executeIfConstructible<MY_OBJECT, Arg1>(MyCallbackHandler());
}
template <typename Arg1, typename ...Args>
void createString(Arg1&& arg1, Args&&... args) {
createString(arg1);
createString(args...);
}
template <typename ...Args>
void createString(Args&&... args) {
std::list<MY_OBJECT> list;
createString(list, args...);
}
};
I don't know if it is the problem (the only problem) but this macro
#define ENABLE_IF(y) typename std::enable_if<y>::type
becomes void when y is true.
So when y is true
template <typename... Types, ENABLE_IF(!IS_CONSTRUCTIBLE(Types...)) = 0>
becomes
template <typename... Types, void = 0>
That can't work. 0 isn't a valid value for void. There are no valid values for void.
And
template <typename X, ENABLE_IF(IS_REFERENCE(X))>
becomes
template <typename X, void>
That is even worse.
I suppose you can define ENABLE_IF to return (in this case) an int
// ...........................................VVVVV
#define ENABLE_IF(y) typename std::enable_if<y, int>::type
remembering the = 0 after every ENABLE_IF
Another problem: now you have
template <typename X, typename Y>
static bool executeIfConstructible(std::function<void()> predicate) {
predicate();
return true;
}
template <typename X, typename Y , ENABLE_IF(!IS_CONSTRUCTIBLE(X,Y))>
static bool executeIfConstructible(std::function<void()> predicate) {
return false;
}
So you have two version of executeIfContructible(): the first one always enabled, the second one enabled only when !IS_CONSTRUCTIBLE(X,Y) is true.
You have to disable the first one when !IS_CONSTRUCTIBLE(X,Y) is false (when IS_CONSTRUCTIBLE(X,Y)) or you'll have an ambiguous call when the second one is enabled.
template <typename X, typename Y , ENABLE_IF(IS_CONSTRUCTIBLE(X,Y))>
static bool executeIfConstructible(std::function<void()> predicate) {
predicate();
return true;
}
template <typename X, typename Y , ENABLE_IF(!IS_CONSTRUCTIBLE(X,Y))>
static bool executeIfConstructible(std::function<void()> predicate) {
return false;
}
Unrequested suggestion: C-style macros are distilled evil. Avoid C-style macros when you can.
For example, instead a macro for ENABLE_IF, define a using
template <bool B>
using EnableIf = typename std::enable_if<B, int>::type;
For IS_REFERENCE and IS_CONSTRUCTIBLE—if you are sure you need them—you can define (starting from C++14) a couple of constexpr template variables
template <bool B>
constexpr bool IsReference = std::is_reference<B>::value;
template <typename ... Ts>
constexpr bool IsConstructible = std::is_constructible<Ts...>::value;

Reader functor in C++

I'm trying to implement a reader functor in C++.
Corresponding Haskell definition is fmap :: (a -> b) -> (r -> a) -> (r -> b)
My C++ version is:
template<class A, class B, class R>
B fmap(const std::function<B(A)> &funcA, const std::function<A(R)> &funcR) {
    return funcA(funcR());
}
std::string function_1(int n);
double function_2(std::string s);
fmap(function_2, function_1);
The error is:
note: candidate template ignored: could not match 'function<type-parameter-0-1 (type-parameter-0-0)>' against 'double (std::__1::basic_string<char>)'
B fmap(const std::function<B(A)> &funcA, const std::function<A(R)> &funcR) {
What is the correct way to implement fmap function?
You can do this with a neat template conversion trick from Template type deduction with std::function
#include <functional>
#include <iostream>
#include <string>
using namespace std;
template<class T>
struct AsFunction
: public AsFunction<decltype(&T::operator())>
{};
template<class ReturnType, class... Args>
struct AsFunction<ReturnType(Args...)> {
using type = std::function<ReturnType(Args...)>;
};
template<class ReturnType, class... Args>
struct AsFunction<ReturnType(*)(Args...)> {
using type = std::function<ReturnType(Args...)>;
};
template<class Class, class ReturnType, class... Args>
struct AsFunction<ReturnType(Class::*)(Args...) const> {
using type = std::function<ReturnType(Args...)>;
};
template<class F>
auto toFunction(F f) -> typename AsFunction<F>::type {
return { f };
}
template<class A, class B, class R>
B fmap(const std::function<B(A)>& funcA, const std::function<A(R)>& funcR, R value) {
return funcA(funcR(value));
}
template <class T>
auto ToFunction(T t) {
return t;
}
std::string function_1(int n) {
return ""s;
}
double function_2(std::string s) {
return 0.0;
}
int main() {
fmap(toFunction(function_2), toFunction(function_1), 5);
return 0;
}
The issue is that template deduction works with exact match on type, without conversions.
You are passing in function pointers, which is not the same type as std::function, so deduction of the template parameters will fail.
The correct way is to take in the callables as template arguments. This ensures deduction will work. A lot of times you don't need to check the signature of the callable, since if it's used in the function you will get a compile time error if it's used in the wrong way.
If you still want to check the signature it's not very hard to do with a type trait.
#include <string>
template<class A, class B>
B fmap(A a, B b) {
return a(b(std::string{}));
}
std::string function_1(int n);
double function_2(std::string s);
fmap(function_2, function_1);
Bartosz Milewski's book "Category Theory for Programmers" (2014-19)
https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/
gives an example of the Writer functor in C++ ... and it's a simpler step from there to produce the Reader functor:
#include <string>
#include <functional>
using namespace std;
template<class R, class A, class B>
function<B(R)> Reader(function<A(R)> m1, function<B(A)> m2)
{
return [m1,m2] (R r) { return m2(m1(r)); };
}
// example
string repeat(string x) {return x+x;}
string i_to_s( int x) {return to_string(x);}
string process(int x) {
return Reader<int, string, string>(i_to_s, repeat)(x);}

A type trait to detect functors using C++17?

Problem description:
C++17 introduces std::invocable<F, Args...>, which is nice to detect if a type... is invocable with the given arguments. However, would there be a way to do it for any arguments for functors (because combinations of the existing traits of the standard library already allow to detect functions, function pointers, function references, member functions...)?
In other words, how to implement the following type trait?
template <class F>
struct is_functor {
static constexpr bool value = /*using F::operator() in derived class works*/;
};
Example of use:
#include <iostream>
#include <type_traits>
struct class0 {
void f();
void g();
};
struct class1 {
void f();
void g();
void operator()(int);
};
struct class2 {
void operator()(int);
void operator()(double);
void operator()(double, double) const noexcept;
};
struct class3 {
template <class... Args> constexpr int operator()(Args&&...);
template <class... Args> constexpr int operator()(Args&&...) const;
};
union union0 {
unsigned int x;
unsigned long long int y;
template <class... Args> constexpr int operator()(Args&&...);
template <class... Args> constexpr int operator()(Args&&...) const;
};
struct final_class final {
template <class... Args> constexpr int operator()(Args&&...);
template <class... Args> constexpr int operator()(Args&&...) const;
};
int main(int argc, char* argv[]) {
std::cout << is_functor<int>::value;
std::cout << is_functor<class0>::value;
std::cout << is_functor<class1>::value;
std::cout << is_functor<class2>::value;
std::cout << is_functor<class3>::value;
std::cout << is_functor<union0>::value;
std::cout << is_functor<final_class>::value << std::endl;
return 0;
}
should output 001111X. In an ideal world, X should be 1, but I don't think it's doable in C++17 (see bonus section).
Edit:
This post seems to present a strategy that solves the problem. However, would there be a better/more elegant way to do it in C++17?
Bonus:
And as a bonus, would there be a way to make it work on final types (but that's completely optional and probably not doable)?
Building on my answer to my answer to this qustion, i was able to solve your problem, including the bonus one :-)
The following is the code posted in the other thread plus some little tweaks to get a special value when an object can't be called. The code needs c++17, so currently no MSVC...
#include<utility>
constexpr size_t max_arity = 10;
struct variadic_t
{
};
struct not_callable_t
{
};
namespace detail
{
// it is templated, to be able to create a
// "sequence" of arbitrary_t's of given size and
// hece, to 'simulate' an arbitrary function signature.
template <size_t>
struct arbitrary_t
{
// this type casts implicitly to anything,
// thus, it can represent an arbitrary type.
template <typename T>
operator T&& ();
template <typename T>
operator T& ();
};
template <typename F, size_t... Is,
typename U = decltype(std::declval<F>()(arbitrary_t<Is>{}...))>
constexpr auto test_signature(std::index_sequence<Is...>)
{
return std::integral_constant<size_t, sizeof...(Is)>{};
}
template <size_t I, typename F>
constexpr auto arity_impl(int) -> decltype(test_signature<F>(std::make_index_sequence<I>{}))
{
return {};
}
template <size_t I, typename F, std::enable_if_t<(I == 0), int> = 0>
constexpr auto arity_impl(...) {
return not_callable_t{};
}
template <size_t I, typename F, std::enable_if_t<(I > 0), int> = 0>
constexpr auto arity_impl(...)
{
// try the int overload which will only work,
// if F takes I-1 arguments. Otherwise this
// overload will be selected and we'll try it
// with one element less.
return arity_impl<I - 1, F>(0);
}
template <typename F, size_t MaxArity = 10>
constexpr auto arity_impl()
{
// start checking function signatures with max_arity + 1 elements
constexpr auto tmp = arity_impl<MaxArity + 1, F>(0);
if constexpr(std::is_same_v<std::decay_t<decltype(tmp)>, not_callable_t>) {
return not_callable_t{};
}
else if constexpr (tmp == MaxArity + 1)
{
// if that works, F is considered variadic
return variadic_t{};
}
else
{
// if not, tmp will be the correct arity of F
return tmp;
}
}
}
template <typename F, size_t MaxArity = max_arity>
constexpr auto arity(F&& f) { return detail::arity_impl<std::decay_t<F>, MaxArity>(); }
template <typename F, size_t MaxArity = max_arity>
constexpr auto arity_v = detail::arity_impl<std::decay_t<F>, MaxArity>();
template <typename F, size_t MaxArity = max_arity>
constexpr bool is_variadic_v = std::is_same_v<std::decay_t<decltype(arity_v<F, MaxArity>)>, variadic_t>;
// HERE'S THE IS_FUNCTOR
template<typename T>
constexpr bool is_functor_v = !std::is_same_v<std::decay_t<decltype(arity_v<T>)>, not_callable_t>;
Given the classes in yout question, the following compiles sucessfully (you can even use variadic lambdas:
constexpr auto lambda_func = [](auto...){};
void test_is_functor() {
static_assert(!is_functor_v<int>);
static_assert(!is_functor_v<class0>);
static_assert(is_functor_v<class1>);
static_assert(is_functor_v<class2>);
static_assert(is_functor_v<class3>);
static_assert(is_functor_v<union0>);
static_assert(is_functor_v<final_class>);
static_assert(is_functor_v<decltype(lambda_func)>);
}
See also a running example here.

index_sequence usage for a class

I want to create a class that will take the following input:
1,make_tuple('A',2,'B')
and inside the class a tuple with static type:
std::tuple<int,char,int,char>
and content of:
{1,'A',2,'B'}
should be created.
Kinda like this- but instead of a function returning the tuple- it should be a tuple that is a member variable of a class:
http://ideone.com/iu1wm5
I know I declare the tuple manually- but I intend to fix that after I figure out how to do this.
I havent found any examples of indicies and template classes- if you have a link to such an example that would also be great.
I know http://cpptruths.blogspot.dk/2012/06/perfect-forwarding-of-parameter-groups.html but he is using vectors- not tuple.
something like this?
#include <iostream>
#include <string>
#include <tuple>
#include <typeinfo>
#include <cstddef>
template<class Ch, class Tr, class Tuple, std::size_t... Is>
void print_tuple_impl(std::basic_ostream<Ch, Tr>& os,
const Tuple & t,
std::index_sequence<Is...>)
{
using swallow = int[]; // guaranties left to right order
(void)swallow {
0, (void(os << (Is == 0 ? "" : ", ") << std::get<Is>(t)), 0)...
};
}
template<class Ch, class Tr, class... Args>
auto operator<<(std::basic_ostream<Ch, Tr>& os, const std::tuple<Args...>& t)
-> std::basic_ostream<Ch, Tr>&
{
os << "(";
print_tuple_impl(os, t, std::index_sequence_for<Args...>{});
return os << ")";
}
template<class Tuple>
struct X {
void print() const {
std::cout << _tuple << std::endl;
}
Tuple _tuple;
};
template<class First, class...Rest>
struct myClass
{
std::tuple<First, Rest...> myTuple;
myClass(First parameterOne, std::tuple<Rest...> param2)
: myTuple(std::tuple_cat(std::make_tuple(parameterOne),
param2))
{
}
void print() const {
std::cout << myTuple << std::endl;
}
};
template<class First, class...Rest>
auto make_myClass(const First& f, const std::tuple<Rest...> rest)
-> myClass<First, Rest...>
{
return { f, rest };
}
using namespace std;
int main()
{
auto mine = make_myClass(1, make_tuple('a', 4));
mine.print();
return 0;
}
I want to create a class that will take the following input:
You don't need to create a class for such a thing. I'm not sure why you want a class that has just a member that is a tuple, that seems less useful than just having a tuple. Here's a genericized solution:
namespace details {
template <typename T>
struct is_tuple : std::false_type { };
template <typename... Args>
struct is_tuple<std::tuple<Args...>> : std::true_type { };
// not a tuple? wrap it with std::make_tuple()
template <typename T,
std::enable_if_t<!is_tuple<std::decay_t<T>>::value>* = nullptr>
auto as_tuple(T&& t) { return std::make_tuple(std::forward<T>(t)); }
// is a tuple?
template <typename T,
std::enable_if_t<is_tuple<std::decay_t<T>>::value>* = nullptr>
decltype(auto) as_tuple(T&& t) { return std::forward<T>(t); }
}
template <typename... Args>
auto tuple_combiner(Args&&... args) {
return std::tuple_cat(details::as_tuple(std::forward<Args>(args))...);
}
Basically, tuple_combiner takes an arbitrary number of arguments which either are or aren't tuples. We call tuple_cat() on a wrapped version of the arguments - the ones that are tuples get forwarded through, and the ones that aren't get wrapped in a tuple first. We also forward everything to minimize copies: