disable branch with "if constexpr" and SFINAE - c++

I want to enable/disable branches at compile time depending of whether a function can be called with certain arguments.
What has to go in the if constexpr condition?
I can get the result type via std::result_of(decltype(add)(A, B)), but how can I check, whether the result type is valid? (i.e. how to I convert this information to a bool?)
const auto add = [](const auto a, const auto b) { return a + b; };
const auto subtract = [](const auto a, const auto b) { return a - b; };
template <typename A, typename B>
void foo(A a, B b) {
if constexpr ( /* can add(a, b) be called? */ ) {
std::cout << "result of add: " << add(a, b) << std::endl;
}
if constexpr ( /* can subtract(a, b) be called? */ ) {
std::cout << "result of subtract: " << subtract(a, b) << std::endl;
}
}

First you need to make your lambdas SFINAE-friendly.
#define RETURNS(...)\
noexcept(noexcept(__VA_ARGS__))\
->decltype(__VA_ARGS__)\
{ return __VA_ARGS__; }
const auto add = [](const auto a, const auto b) RETURNS( a + b );
const auto subtract = [](const auto a, const auto b) RETURNS( a - b );
Now add and subract can be tested in a SFINAE context.
namespace details {
template<class, class, class...>
struct can_invoke:std::false_type {};
template<class F, class...Args>
struct can_invoke<F, std::void_t< std::result_of_t< F&&(Args&&...) > >, Args... >:
std::true_type
{};
}
template<class F, class...Args>
using can_invoke_t = details::can_invoke<F, Args...>;
template<class F, class...Args>
constexpr can_invoke_t< F, Args... >
can_invoke( F&&, Args&&... ){ return {}; }
and we are ready:
template <typename A, typename B>
void foo(A a, B b) {
if constexpr ( can_invoke( add, a, b ) ) {
std::cout << "result of add: " << add(a, b) << std::endl;
}
if constexpr ( can_invoke( subtract, a, b ) {
std::cout << "result of subtract: " << subtract(a, b) << std::endl;
}
}
this is c++14; in c++11 it is more awkward, in c++17 more elegant as they already have a can invoke type trait (which handles a few more corner cases; however, it also expects you to call add with std::invoke).
In c++17 I sort of like this trick:
template<class F>
constexpr auto invoke_test( F&& ) {
return [](auto&&...args) ->
can_invoke_t<F, decltype(args)...>
{ return {}; };
}
template <typename A, typename B>
void foo(A a, B b) {
if constexpr ( invoke_test( add )( a, b ) ) {
std::cout << "result of add: " << add(a, b) << std::endl;
}
if constexpr ( invoke_test( subtract )( a, b ) {
std::cout << "result of subtract: " << subtract(a, b) << std::endl;
}
}
where invoke_test takes a callable, and returns a callable whose only job is to answer "the original callable be invoked with the args you passed me".

You can put SFINAE to the return type and let function overloading tell whether a call can be made. A helper function can_be_called can be implemented as following:
#include <type_traits>
template<class Func, class... Args>
constexpr auto
can_be_called(Func&& func, Args&&... args)
-> decltype(
(std::forward<Func>(func)(std::forward<Args>(args)...)
, bool{}))
{ return true; }
struct Dummy {
template<class T> constexpr Dummy(T&&) {}
};
template<class... Args>
constexpr bool
can_be_called(Dummy, Args&&...) { return false; }
// test
#include <iostream>
void foo(int, int) {}
struct A{};
int main() {
if constexpr( can_be_called(foo, 1, 2) ) {
std::cout << "OK\n";
}
if constexpr ( !can_be_called(foo, A{}, 2) ) {
std::cout << "NO\n";
}
}

Related

add to queue a template function c++

i search on google how to store and to execute functions (template function or not) passing in queue but i didn't find an enough good answer...
this is my code
Window.h
struct QueueEventFunction {
std::vector<std::function<void()>> v; // stores the functions and arguments
// as zero argument lambdas
template <typename F,/*template <typename U, typename = std::allocator<U> >*/ typename ...Args>
void Enqueue(F (*f), Args... args)
{
v.push_back([=] { f(args...); }); // add function and arguments
// as zero argument lambdas
// that capture the function and arguments
}
void CallAll()
{
for (auto f : v)
f(); // calls all the functions
}
};
class Window : public sf::RenderWindow {
public:
Window(sf::VideoMode window, const std::string& title, sf::Uint32 style = 7U, sf::ContextSettings settings = sf::ContextSettings());
~Window();
template <typename F, /*template <typename ...U > */typename ...Args>
void addQueue(F (*f), Args...args);
void execQueue();
private:
QueueEventFunction queue;
}
template <typename F, /*template <typename ...U >*/ typename ...Args>
void Window::addQueue(F (*f), Args...args) {
queue.Enqueue(f, std::forward<Args>(args)...);
}
void Window::execQueue() {
queue.CallAll();
}
TestWindow.cpp
template<typename T>
void add(T a, T b) {
return a + b;
}
class foo{
public:
template<typename T> T add( T a, T b){ return a+ b;}
};
int main() {
Window window(sf::VideoMode(600, 600), "Test Window",7U,sf::ContextSettings());
window.addQueue(add<int>,1,2); // doesn't work
foo bar;
window.addQueue(&foo::add<int>,1,2); // doesn"t work
window.addQueue(bar.add<int>(1,2)); // doesn"t work
return 0;
}
i got a external symbol error.
and if i put a function member class it simply doesn't work. (compilation error)
have you got an idea to correctly make the function addQueue<> with args ?
The big problem with your code is that you take the function pointer as a pointer
template <typename F, typename ...Args>
void Enqueue(F (*f), Args... args)
and
template <typename F, typename ...Args>
void addQueue(F (*f), Args...args);
What you really want is
template <typename F, typename ...Args>
void Enqueue(F f, Args... args)
and
template <typename F, typename ...Args>
void addQueue(F f, Args...args);
And then you can pass any callable thing. Then you can use it with results of bind, lambdas, class member functions, class static member functions, and normal functions.
Then you can use it like
template<typename T>
int add(T a, T b) {
std::cout << "add(" << a << "," << b << ") -> " << a+b << "\n";
return a + b;
}
class foo{
public:
template<typename T>
T add( T a, T b) {
std::cout << "foo::add(" << a << "," << b << ") -> " << a+b << "\n";
return a + b;
}
template<typename T>
static T static_add( T a, T b) {
std::cout << "foo::static_add(" << a << "," << b << ") -> " << a+b << "\n";
return a + b;
}
};
int main() {
Window window(sf::VideoMode(600, 600),"Test Window",7U,sf::ContextSettings());
foo bar;
auto bar_add = [&bar](auto a,auto b){ return bar.add<int>(a,b); };
auto bind_add = std::bind(&foo::add<int>, &bar, std::placeholders::_1, std::placeholders::_2);
window.addQueue(bind_add,5,2);
window.addQueue(bar_add,5,2);
window.addQueue(add<int>,5,2);
window.addQueue(foo::static_add<int>,5,2);
window.execQueue();
return 0;
}
Try it here https://www.onlinegdb.com/t9WczrL-c

is there any way to obtain the callable's argument list and then use it as parameter pack in template?

callable should be any function pointer, std::function or lambda. I want to obtain their argument list and use them as parameter pack:
template <typename callable_T>
class callback2_t
{
public:
using callable_t = callable_T;
using ret_T = some_magic<callable_T>::ret_t;
using data_T = the_first_type<argTs>;
...
static ret_T _callback(some_magic<callable_T>::argTs... args);
};
The purpose is to simplify follow templates to make it work for all kind of callable without creating alias:
// other library only accept function pointer as callback, I want to wrap it to remove the callback when data go out of scope.
template <typename callable_T, typename ret_T, typename data_T, typename ...arg_Ts>
class callback_t
{
using callable_t = callable_T;
public:
callback_t(const char* signal, callable_t callable, data_T data)
: f_{std::move(callable)}, data_{std::move(data)}
{
std::cout << signal << " " << typeid(callable).name() << std::endl;
//register_callback(signal, _callback, this);
}
~callback_t()
{
//unregister_callback(signal);
}
void test_callback(arg_Ts... args)
{
_callback(args..., this);
}
private:
callable_t f_;
data_T data_;
static ret_T _callback(arg_Ts... args, callback_t * self)
{
return self->f_(&self->data_, args...);
}
};
// I donot want convert function pointer to std::function
// if possible. std::function is a heavy class.
template <typename ret_T, typename data_T, typename ...arg_Ts>
using fp_callback_t = callback_t<ret_T(*)(void *, arg_Ts...), ret_T, data_T, arg_Ts...>;
template <typename ret_T, typename data_T, typename ...arg_Ts>
using func_callback_t = callback_t<std::function<ret_T(void *, arg_Ts...)>, ret_T, data_T, arg_Ts...>;
We can use the template like this:
struct A{float x;};
struct B{int x;};
struct C{uint x;};
int func1(void * data, A* a)
{
auto c = reinterpret_cast<C*>(data);
std::cout<< a->x << ", " << c->x << std::endl;
return a->x + c->x;
}
void func2(void *data, B* b, C* c)
{
auto a = reinterpret_cast<A*>(data);
std::cout << b->x << ", " << c->x << ", " << a->x << std::endl;
}
int main()
{
A a1{-10.5f};
B b1 {5};
C c1{300};
auto callback1 = fp_callback_t<int, C, A*>("signal1", &func1, c1);
callback1.test_callback(&a1);
auto callback2 = fp_callback_t<void, A, B*, C*>("signal2", &func2, a1);
callback2.test_callback(&b1, &c1);
std::function<int(void*, A*)> fc1 = [=](void* data, A* a){
auto c = reinterpret_cast<C*>(data);
std::cout<< a->x << ", " << c->x << ", " << a1.x << std::endl;
return (int)a1.x;
};
std::function<void(void*, B*, C*)> fc2 = [=](void* data, B* b, C* c){
auto a = reinterpret_cast<A*>(data);
std::cout << b->x << ", " << c->x << ", " << a->x << ", " << c1.x << std::endl;
};
auto callback3 = func_callback_t<int, C, A*>("signal3", fc1, c1);
callback3.test_callback(&a1);
auto callback4 = func_callback_t<void, A, B*, C*>("signal4", fc2, a1);
callback4.test_callback(&b1, &c1);
return 0;
}
The out put is:
signal1 PFiPvP1AE
-10.5, 300
signal2 PFvPvP1BP1CE
5, 300, -10.5
signal3 NSt3__18functionIFiPvP1AEEE
-10.5, 300, -10.5
signal4 NSt3__18functionIFvPvP1BP1CEEE
5, 300, -10.5, 300
The deduction should work without specialize template parameters explicitly; I want to avoid alias; It should work with function pointer, std::function and lambda; the callable_t should be as it is given instead of casting all of them to std::function. like following:
auto callback1 = callback2_t("signal1", &func1, c1);
callback1.test_callback(&a1);
auto callback2 = callback2_t("signal2", &func2, a1);
callback2.test_callback(&b1, &c1);
std::function<int(void*, A*)> fc1 = [=](void* data, A* a){
auto c = reinterpret_cast<C*>(data);
std::cout<< a->x << ", " << c->x << ", " << a1.x << std::endl;
return (int)a1.x;
};
auto callback3 = callback2_t("signal3", fc1, c1);
callback3.test_callback(&a1);
auto lambda1 = [=](void* data, B* b, C* c){
auto a = reinterpret_cast<A*>(data);
std::cout << b->x << ", " << c->x << ", " << a->x << ", " << c1.x << std::endl;
};
auto callback4 = callback2_t("signal4", lambda1, a1);
callback4.test_callback(&b1, &c1);
You don't need to deduce the parameters at all. Just let the template soak them up and forward them to the callable.
template <typename callable_T, typename data_T>
class callback_t
{
using callable_t = callable_T;
public:
callback_t(const char* signal, callable_t callable, data_T data)
: f_{std::move(callable)}, data_{std::move(data)}
{
}
template<typename...arg_Ts>
auto test_callback(arg_Ts... args)
{
return _callback(this, args...);
}
private:
callable_t f_;
data_T data_;
template<typename...arg_Ts>
static auto _callback(callback_t * self, arg_Ts... args)
{
return self->f_(&self->data_, args...);
}
};
Works great even if operator() is overloaded:
int test()
{
callback_t cc("test", [](auto x, auto y){ return *x + y;}, 42);
return cc.test_callback(9); // returns 42 + 9 = 51
}
That was an interesting quiz =) The trick was to pass pointer to lambda::operator() and let type deduction work:
template <typename Ret, typename ... Args>
struct Callback {
Callback() {
std::cout << "Created " << typeid(*this).name() << "\n";
}
};
template <typename Ret, typename ... Args>
Callback<Ret, Args...> create_callback(std::function<Ret (Args...)> const &fn) {
std::cout << "Function!\n";
return Callback<Ret, Args...>();
}
template <typename Ret, typename ... Args>
Callback<Ret, Args...> create_callback(Ret (*fn)(Args...)) {
std::cout << "Function pointer!\n";
return Callback<Ret, Args...>();
}
template <typename Lambda, typename Ret, typename ... Args>
Callback<Ret, Args...> create_callback_lambda(Lambda const &, Ret (Lambda::*)(Args...) const) {
std::cout << "Lambda!\n";
return Callback<Ret, Args...>();
}
template <typename Callable>
auto create_callback(Callable const &c) {
return create_callback_lambda(c, &Callable::operator());
}

Stopping generic C++14 `curry` function recursion

I'm trying to implement a generic curry function in C++14 that takes a callable object as an input parameter and allows currying.
Desired syntax:
auto sum3 = [](int x, int y, int z){ return x + y + z; };
int main()
{
assert(curry(sum3)(1)(1)(1) == 3);
auto plus2 = curry(sum3)(1)(1);
assert(plus2(1) == 3);
assert(plus2(3) == 5);
}
My implementation idea is as follows: have the curry function return an unary function that binds its argument to a future call to the original function, recursively. Call the bound original function on the "last recursive step".
Detecting the "last recursive step" is the problematic part.
My idea was detecting whether or not the current bound function (during the recursion) was legally callable with zero arguments, using a is_zero_callable type trait:
template <typename...>
using void_t = void;
template <typename, typename = void>
class is_zero_callable : public std::false_type
{
};
template <typename T>
class is_zero_callable<T, void_t<decltype(std::declval<T>()())>>
: public std::true_type
{
};
Unfortunately, I cannot seem to find a way to check the correct function for zero-argument "callability" - I need to somehow check if the function that will be returned from the currently bound function is zero-callable.
Here's what I've got so far (godbolt link):
template <typename TF, bool TLastStep>
struct curry_impl;
// Base case (last step).
// `f` is a function callable with no arguments.
// Call it and return.
template <typename TF>
struct curry_impl<TF, true>
{
static auto exec(TF f)
{
return f();
}
};
// Recursive case.
template <typename TF, bool TLastStep>
struct curry_impl
{
static auto exec(TF f)
{
// Bind `x` to subsequent calls.
return [=](auto x)
{
// This is `f`, with `x` bound as the first argument.
// (`f` is the original function only on the first recursive
// step.)
auto bound_f = [=](auto... xs)
{
return f(x, xs...);
};
// Problem: how to detect if we need to stop the recursion?
using last_step = std::integral_constant<bool, /* ??? */>;
// `is_zero_callable<decltype(bound_f)>{}` will not work,
// because `bound_f` is variadic and always zero-callable.
// Curry recursively.
return curry_impl<decltype(bound_f),
last_step{}>::exec(bound_f);
};
}
};
// Interface function.
template <typename TF>
auto curry(TF f)
{
return curry_impl<TF, is_zero_callable<decltype(f)>{}>::exec(f);
}
Is my approach/intuition viable? (Is it actually possible to stop the recursion by detecting whether or not we've reached a zero-arg-callable version of the original function?)
...or is there a better way of solving this problem?
(Please ignore the missing perfect forwarding and the lack of polish in the example code.)
(Note that I've tested this currying implementation using an user-specified template int TArity parameter to stop the recursion, and it worked properly. Having the user manually specify the arity of the original f function is unacceptable, however.)
The minimal changes required to make this work in Clang is
auto bound_f = [=](auto... xs) -> decltype(f(x, xs...))
// ^^^^^^^^^^^^^^^^^^^^^^^^^
{
return f(x, xs...);
};
using last_step = std::integral_constant<bool,
is_zero_callable<decltype(bound_f)>{}>;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Explicitly specifying the return type should make it SFINAE-friendly and capable of being detected by is_zero_callable. Unfortunately, GCC is unhappy with this, probably due to a bug.
A generic lambda is basically a class with a templated operator(), so we can just write it ourselves:
template<class F, class T>
struct bound_function {
F f;
T arg;
template<class... Args>
auto operator()(Args... args) const -> decltype(f(arg, args...)){
return f(arg, args...);
}
};
Note that I'm imitating the semantics of the generic lambda here and making the operator() const. A full-featured implementation will likely want to overload on constness and value categories.
Then
auto bound_f = bound_function<TF, decltype(x)>{f, x};
works in both GCC and Clang, but has a theoretical problem: when only f(arg) is valid (and not with extra arguments), then instantiating bound_function (which instantiates a declaration of its operator()) is ill-formed NDR because every valid specialization of operator()'s declaration requires an empty parameter pack.
To avoid this, let's specialize bound_function for the "no further arguments needed" case. And since we are computing this information anyway, let's just express it in a member typedef.
template<class F, class T, class = void>
struct bound_function {
using zero_callable = std::false_type;
F f;
T arg;
template<class... Args>
auto operator()(Args... args) const -> decltype(f(arg, args...)){
return f(arg, args...);
}
};
template<class F, class T>
struct bound_function<F, T, void_t<decltype(std::declval<const F&>()(std::declval<const T&>()))>> {
using zero_callable = std::true_type;
F f;
T arg;
decltype(auto) operator()() const {
return f(arg);
}
};
Then
auto bound_f = bound_function<TF, decltype(x)>{f, x};
using last_step = typename decltype(bound_f)::zero_callable;
under file check. please.
https://github.com/sim9108/Study2/blob/master/SDKs/curryFunction.cpp
// ConsoleApplication4.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <functional>
#include <type_traits>
// core function
template<typename FN, std::size_t N>
struct curry
{
FN fn_;
curry(FN fn) :fn_{ fn }
{
}
template<typename... TS, typename = std::enable_if_t< (N - sizeof...(TS)) != 0, int >>
auto operator()(TS... ts1) {
auto fn = [f = this->fn_, ts1...](auto... args) mutable {
return f(ts1..., args...);
};
return curry<decltype(fn), N - sizeof...(TS)>(fn);
}
template<typename... TS, typename Z = void, typename = std::enable_if_t< (N - sizeof...(TS)) == 0, int > >
auto operator()(TS... ts1) {
return fn_(ts1...);
}
};
//general make curry function
template<typename R, typename... Args>
auto make_curry(R(&f)(Args...)) {
auto fn = [&f](Args... args) {
return f(args...);
};
return curry<decltype(fn), sizeof...(Args)>(fn);
}
//general make curry member function
template<typename C, typename R, typename... Args>
auto make_curry(R(C::*f)(Args...), C c) {
auto fn = [f, c](Args... args) mutable {
return (c.*f)(args...);
};
return curry<decltype(fn), sizeof...(Args)>(fn);
}
template<typename C, typename R, typename... Args>
auto make_curry(R(C::*f)(Args...) const, C c) {
auto fn = [f, c](Args... args) mutable {
return (c.*f)(args...);
};
return curry<decltype(fn), sizeof...(Args)>(fn);
}
//general make curry lambda function
template<typename C>
auto make_curry(C&& c) {
using CR = std::remove_reference_t<C>;
return make_curry(&CR::operator(), c);
}
using std::string;
using std::function;
string func(string a, string b, string c) {
return "general function:" + a + b + c;
}
struct A {
string func(string a, string b, string c) {
return "member function:" + a + b + c;
};
};
int main(int argc, char* argv[])
{
{ //general function curry
auto c = make_curry(func);
auto m1 = c("t1")("t2")("t3");
auto m2 = c("test1")("test2")("test3");
auto m3 = c("m1");
auto m4 = m3("m2");
auto m5 = m4("m3");
std::cout << m5 << std::endl;
std::cout << m2 << std::endl;
std::cout << m5 << std::endl;
}
{ //member function curry
A a;
auto c = make_curry(&A::func, a);
auto m1 = c("t1")("t2")("t3");
auto m2 = c("test1")("test2")("test3");
auto m3 = c("m1");
auto m4 = m3("m2");
auto m5 = m4("m3");
std::cout << m1 << std::endl;
std::cout << m2 << std::endl;
std::cout << m5 << std::endl;
}
{ //lambda function curry
auto fn = [](string a, string b, string c) {
return "lambda function:" + a + b + c;
};
auto c = make_curry(fn);
auto m1 = c("t1")("t2")("t3");
auto m2 = c("test1")("test2")("test3");
auto m3 = c("m1");
auto m4 = m3("m2");
auto m5 = m4("m3");
std::cout << m1 << std::endl;
std::cout << m2 << std::endl;
std::cout << m5 << std::endl;
}
auto func3 = make_curry(func);
std::cout << func3("Hello, ")( "World!", " !hi") << std::endl;
std::cout << func3("Hello, ","World!")(" !hi") << std::endl;
std::cout << func3("Hello, ","World!", " !hi") << std::endl;
std::cout << func3()("Hello, ", "World!", " !hi") << std::endl;
return 0;
}

Constructor permutations for passing parameters in arbitrary order

Say I have 5 classes, A-E.
I want to create a class Gadget that can be constructed from 0-5 parameters which are constrained to be a const reference to types A,B,C,D, or E in any order and without duplicates.
What is the cleanest way to implement this?
The following solves your problem:
#include <type_traits>
#include <tuple>
// find the index of a type in a list of types,
// return sizeof...(Ts) if T is not found
template< typename T, typename... Ts >
struct index_by_type : std::integral_constant< std::size_t, 0 > {};
template< typename T, typename... Ts >
struct index_by_type< T, T, Ts... > : std::integral_constant< std::size_t, 0 >
{
static_assert( index_by_type< T, Ts... >::value == sizeof...( Ts ), "duplicate type detected" );
};
template< typename T, typename U, typename... Ts >
struct index_by_type< T, U, Ts... > : std::integral_constant< std::size_t, index_by_type< T, Ts... >::value + 1 > {};
// get the element from either "us" if possible...
template< std::size_t I, std::size_t J, typename T, typename... Us, typename... Ts >
auto get_by_index( const std::tuple< Us... >&, const std::tuple< Ts... >& ts )
-> typename std::enable_if< I == sizeof...( Us ), const T& >::type
{
return std::get< J >( ts );
}
// ...get the element from "ts" otherwise
template< std::size_t I, std::size_t J, typename T, typename... Us, typename... Ts >
auto get_by_index( const std::tuple< Us... >& us, const std::tuple< Ts... >& )
-> typename std::enable_if< I != sizeof...( Us ), const T& >::type
{
return std::get< I >( us );
}
// helper to validate that all Us are in Ts...
template< bool > struct invalide_type;
template<> struct invalide_type< true > : std::true_type {};
template< std::size_t... > void validate_types() {}
template< typename T >
struct dflt
{
static const T value;
};
template< typename T >
const T dflt< T >::value;
// reorder parameters
template< typename... Ts, typename... Us >
std::tuple< const Ts&... > ordered_tie( const Us&... us )
{
auto t1 = std::tie( us... );
auto t2 = std::tie( dflt< Ts >::value... );
validate_types< invalide_type< index_by_type< const Us&, const Ts&... >::value != sizeof...( Ts ) >::value... >();
return std::tie( get_by_index< index_by_type< const Ts&, const Us&... >::value,
index_by_type< const Ts&, const Ts&... >::value, Ts >( t1, t2 )... );
}
struct A {};
struct B {};
struct C {};
struct Gadget
{
A a;
B b;
C c;
explicit Gadget( const std::tuple< const A&, const B&, const C& >& t )
: a( std::get<0>(t) ),
b( std::get<1>(t) ),
c( std::get<2>(t) )
{}
template< typename... Ts >
Gadget( const Ts&... ts ) : Gadget( ordered_tie< A, B, C >( ts... ) ) {}
};
int main()
{
A a;
B b;
C c;
Gadget g1( a, b, c );
Gadget g2( b, c, a );
Gadget g3( a, b ); // uses a default-constructed C
Gadget g4( a, c ); // uses a default-constructed B
Gadget g5( c ); // uses a default-constructed A and B
Gadget g6; // uses a default-constructed A, B and C
// fails to compile:
// Gadget gf1( a, a ); // duplicate type
// Gadget gf2( a, b, 42 ); // invalid type
}
Live example
Easy just use variadic templates and a static_assert
template <typename ... Types>
struct thing
{
static_assert(sizeof...(Types) <= 5,"Too many objects passed");
};
int main()
{
thing<int,float,double,int,int> a;
return 0;
}
Preventing duplicates might be tricky, I still have to think of that one.
Honestly I can't think of any un-painful way to ensure that all the types are different but the solution will likely involve std::is_same one definite way to make it work would be to have specializations for 0 - 5 types and use a static_assert to check all the combinations in each specialization, this will definitely be a pain though.
EDIT: well this was fun
template <typename ... Types>
struct thing
{
static_assert(sizeof ... (Types) <= 5,"Too big");
};
template <>
struct thing<> {};
template <typename A>
struct thing<A>{};
template <typename A, typename B>
struct thing<A,B>
{
static_assert(!std::is_same<A,B>::value,"Bad");
};
template <typename A, typename B, typename C>
struct thing<A,B,C>
{
static_assert(!std::is_same<A,B>::value &&
!std::is_same<A,C>::value &&
!std::is_same<C,B>::value,"Bad");
};
template <typename A, typename B, typename C, typename D>
struct thing<A,B,C,D>
{
static_assert(!std::is_same<A,B>::value &&
!std::is_same<A,C>::value &&
!std::is_same<C,B>::value &&
!std::is_same<C,D>::value &&
!std::is_same<B,D>::value &&
!std::is_same<A,D>::value,"Bad");
};
template <typename A, typename B, typename C, typename D, typename E>
struct thing<A,B,C,D,E>
{
static_assert(!std::is_same<A,B>::value &&
!std::is_same<A,C>::value &&
!std::is_same<C,B>::value &&
!std::is_same<C,D>::value &&
!std::is_same<B,D>::value &&
!std::is_same<A,D>::value &&
!std::is_same<A,E>::value &&
!std::is_same<B,E>::value &&
!std::is_same<C,E>::value &&
!std::is_same<D,E>::value,"Bad");
};
int main()
{
thing<> a;
thing<int,float,int> b; //error
thing<int,float,double,size_t,char> c;
thing<int,float,double,size_t,char,long> d; //error
return 0;
}
To create a more general approach what you have to do is create a compile time combination meta function
The question asks for a Gaget class that can be constructed with [0-5] number of parameters constrained to 5 different types without duplication, and with any order. With the help of templates it's doable; below is an example for two parameters, and it's easily extensible to 5 parameters.
class A
{
};
class B
{
};
template<typename T> struct is_A
{
enum { value = false };
};
template<> struct is_A<A>
{
enum { value = true };
};
template<typename T> struct is_B
{
enum { value = false };
};
template<> struct is_B<B>
{
enum { value = true };
};
template <bool V> struct bool_to_count
{
enum {value = V ? 1 : 0};
};
class Gaget
{
public:
template <typename T1> Gaget(const T1& t1)
{
static_assert(is_A<T1>::value || is_B<T1>::value, "T1 can only be A or B");
if (is_A<T1>::value)
{
m_a = *reinterpret_cast<const A*>(&t1);
}
if (is_B<T1>::value)
{
m_b = *reinterpret_cast<const B*>(&t1);
}
}
template <typename T1, typename T2> Gaget(const T1& t1, const T2& t2)
{
static_assert(is_A<T1>::value || is_B<T1>::value, "T1 can only be A or B");
static_assert(is_A<T2>::value || is_B<T2>::value, "T2 can only be A or B");
const int countA = bool_to_count<is_A<T1>::value>::value
+ bool_to_count<is_A<T2>::value>::value;
static_assert(countA == 1, "One and only one A is allowed");
const int countB = bool_to_count<is_B<T1>::value>::value
+ bool_to_count<is_B<T2>::value>::value;
static_assert(countA == 1, "One and only one B is allowed");
if(is_A<T1>::value)
{
// it's safe because it's only executed when T1 is A;
// same with all following
m_a = *reinterpret_cast<const A*>(&t1);
}
if(is_B<T1>::value)
{
m_b = *reinterpret_cast<const B*>(&t1);
}
if (is_A<T2>::value)
{
m_a = *reinterpret_cast<const A*>(&t2);
}
if (is_B<T2>::value)
{
m_b = *reinterpret_cast<const B*>(&t2);
}
}
private:
A m_a;
B m_b;
};
void foo(const A& a, const B& b)
{
auto x1 = Gaget(b,a);
auto x2 = Gaget(a,b);
auto x3 = Gaget(a);
auto x4 = Gaget(b);
// auto x5 = Gaget(a,a); // error
// auto x6 = Gaget(b,b); // error
}
If you are willing to make compromises on the syntax, you can do it with the Builder pattern. The usage would look like this:
Gadget g = Gadget::builder(c)(a)(b)();
Yes, this syntax is not very nice and perhaps a bit obscure but it is a reasonable compromise. The good news is that you avoid the combinatorial explosion: This solutions scales linearly with the number of arguments. One downside is that duplicate arguments are detected only at runtime.
Sample code for 3 types (may contain errors):
#include <iostream>
#include <stdexcept>
struct A { char value = ' '; };
struct B { char value = ' '; };
struct C { char value = ' '; };
struct state { A a; B b; C c; };
class Gadget {
private:
Gadget(state s) : s(s) { };
state s;
public:
class builder {
public:
template <class T>
builder(T t) { reference(t) = t; }
template <class T>
builder& operator()(T t) { return assign(reference(t), t); }
Gadget operator()() { return Gadget(s); }
private:
template <class T>
builder& assign(T& self, T t) {
if (self.value != ' ')
throw std::logic_error("members can be initialized only once");
self = t;
return *this;
}
A& reference(A ) { return s.a; }
B& reference(B ) { return s.b; }
C& reference(C ) { return s.c; }
state s;
};
friend std::ostream& operator<<(std::ostream& out, const Gadget& g) {
out << "A: " << g.s.a.value << std::endl;
out << "B: " << g.s.b.value << std::endl;
return out << "C: " << g.s.c.value << std::endl;
}
};
int main() {
A a; a.value = 'a';
B b; b.value = 'b';
C c; c.value = 'c';
Gadget g = Gadget::builder(c)(a)(b)();
std::cout << "Gadget:\n" << g << std::endl;
}
Far from perfect but I personally find it easier to read and understand than the solutions using template metaprogramming.
Here is a working solution, still not sure of the optimal solution.
#include <iostream>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/set.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/has_key.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/for_each.hpp>
struct A{
A() { std::cout << "A default constructor" << std::endl; }
~A() { std::cout << "A destructor" << std::endl; }
A( const A& ) { std::cout << "A copy constructor" << std::endl; }
A( A&& ) { std::cout << "A move constructor" << std::endl; }
};
struct B{
B() { std::cout << "B default constructor" << std::endl; }
~B() { std::cout << "B destructor" << std::endl; }
B( const B& ) { std::cout << "B copy constructor" << std::endl; }
B( B&& ) { std::cout << "B move constructor" << std::endl; }
};
struct C{
C() { std::cout << "C default constructor" << std::endl; }
~C() { std::cout << "C destructor" << std::endl; }
C( const C& ) { std::cout << "C copy constructor" << std::endl; }
C( C&& ) { std::cout << "C move constructor" << std::endl; }
};
struct D{
D() { std::cout << "D default constructor" << std::endl; }
~D() { std::cout << "D destructor" << std::endl; }
D( const D& ) { std::cout << "D copy constructor" << std::endl; }
D( D&& ) { std::cout << "D move constructor" << std::endl; }
};
struct E{
E() { std::cout << "E default constructor" << std::endl; }
~E() { std::cout << "E destructor" << std::endl; }
E( const E& ) { std::cout << "E copy constructor" << std::endl; }
E( E&& ) { std::cout << "E move constructor" << std::endl; }
};
class Gadget
{
struct call_setters
{
Gadget& self;
call_setters( Gadget& self_ ) : self( self_ ){}
template< typename T >
void operator()( T& t ) const
{
self.set( t );
}
};
public:
template< typename... Args >
Gadget( const Args&... args )
{
using namespace boost::mpl;
using namespace boost::mpl::placeholders;
typedef vector<A, B, C, D, E> allowed_args;
static_assert(sizeof...(Args) <= size<allowed_args>::value, "Too many arguments");
typedef typename fold< vector<Args...>
, set0<>
, insert<_1, _2>
>::type unique_args;
static_assert(size<unique_args>::value == sizeof...(Args), "Duplicate argument types");
typedef typename fold< allowed_args
, int_<0>
, if_< has_key<unique_args, _2 >, next<_1>, _1 >
>::type allowed_arg_count;
static_assert(allowed_arg_count::value == sizeof...(Args), "One or more argument types are not allowed");
namespace bf = boost::fusion;
bf::for_each( bf::vector<const Args&...>( args... ), call_setters{ *this } );
}
void set( const A& ) { std::cout << "Set A" << std::endl; }
void set( const B& ) { std::cout << "Set B" << std::endl; }
void set( const C& ) { std::cout << "Set C" << std::endl; }
void set( const D& ) { std::cout << "Set D" << std::endl; }
void set( const E& ) { std::cout << "Set E" << std::endl; }
};
int main()
{
Gadget{ A{}, E{}, C{}, D{}, B{} };
}
Live Demo

function composition in C++ / C++11

I am currently coding some cryptographic algorithms in C++11 that require a lot of function compositions. There are 2 types of composition I have to deal with :
Compose a function on itself a variable number of times. Mathematically, for a certain function F, F^n(x) = (F^{n-1} o F)(x) = F^{n-1}(F(x)).
Compose different functions together. For example, for some functions f,g,h,i,j and k of the same type, I'll have f(g(h(i(j(k(x)))))).
In my case, I'm using the following definition of F :
const std::vector<uint8_t> F(const std::vector<uint8_t> &x);
I would like to compose this function on itself n times. I have implemented the composition in a simple recursive way which is working fine :
const std::vector<uint8_t> compose(const uint8_t n, const std::vector<uint8_t> &x)
{
if(n > 1)
return compose(n-1, F(x));
return F(x);
}
For this case, is there a more efficient way an proper way to implement this composition using c++11 but without using BOOST ?
It would be great to use this form if it is possible of course :
answer = compose<4>(F)(x); // Same as 'answer = F^4(x) = F(F(F(F(x))))'
For the second case, I would like to implement the composition of a variable number of functions. For a given set of functions F0, F1, ..., Fn having the same definition as F, is there an efficient and proper way to compose them where n is variable ?
I think variadic template would be useful here, but I don't know how to use them in that case.
Thanks for your help.
Something along these lines, perhaps (untested):
template <typename F>
class Composer {
int n_;
F f_;
public:
Composer(int n, F f) : n_(n), f_(f) {}
template <typename T>
T operator()(T x) const {
int n = n_;
while (n--) {
x = f_(x);
}
return x;
}
};
template <int N, typename F>
Composer<F> compose(F f) {
return Composer<F>(N, f);
}
EDIT: And for the second case (tested this time):
#include <iostream>
template <typename F0, typename... F>
class Composer2 {
F0 f0_;
Composer2<F...> tail_;
public:
Composer2(F0 f0, F... f) : f0_(f0), tail_(f...) {}
template <typename T>
T operator() (const T& x) const {
return f0_(tail_(x));
}
};
template <typename F>
class Composer2<F> {
F f_;
public:
Composer2(F f) : f_(f) {}
template <typename T>
T operator() (const T& x) const {
return f_(x);
}
};
template <typename... F>
Composer2<F...> compose2(F... f) {
return Composer2<F...>(f...);
}
int f(int x) { return x + 1; }
int g(int x) { return x * 2; }
int h(int x) { return x - 1; }
int main() {
std::cout << compose2(f, g, h)(42);
return 0;
}
Thanks for the fun question, Gabriel of year 2013.
Here is a solution. It works in c++14.
#include <functional>
#include <iostream>
using std::function;
// binary function composition for arbitrary types
template <class F, class G> auto compose(F f, G g) {
return [f, g](auto x) { return f(g(x)); };
}
// for convienience
template <class F, class G> auto operator*(F f, G g) { return compose(f, g); }
// composition for n arguments
template <class F, typename... Fs> auto compose(F f, Fs &&... fs) {
return f * compose(fs...);
}
// composition for n copies of f
template <int i, class F>
// must wrap chain in a struct to allow partial template specialization
struct multi {
static F chain(F f) { return f * multi<i - 1, F>::chain(f); }
};
template <class F> struct multi<2, F> {
static F chain(F f) { return f * f; }
};
template <int i, class F> F compose(F f) { return multi<i, F>::chain(f); }
int main(int argc, char const *argv[]) {
function<double(int)> f = [](auto i) { return i + 3; };
function<int(double)> g = [](auto i) { return i * 2; };
function<int(int)> h = [](auto i) { return i + 1; };
std::cout << '\n'
<< "9 == " << compose(f, g, f)(0) << '\n'
<< "5 == " << (f * g * h)(0) << '\n'
<< "100 == " << compose<100>(h)(0) << '\n';
return 0;
}
You can define
Matrix compose(Matrix f, Matrix g);
or
Rotation compose(Rotation f, Rotation g);
to reuse this code for all sorts of things.
A very general example (g++ -std=c++1y composition.cpp):
// ---------------------------------------------------------
// "test" part
// ---------------------------------------------------------
int f(int a) { return 2*a; }
double g(int a) { return a+2.5; }
double h(double a) { return 2.5*a; }
double i(double a) { return 2.5-a; }
class Functor {
double x;
public:
Functor (double x_) : x(x_) { }
double operator() (double a) { return a*x; }
};
// ---------------------------------------------------------
// ---------------------------------------------------------
int main () {
auto l1 = [] (double a) { return a/3; };
auto l2 = [] (double a) { return 3.5+a; };
Functor fu {4.5};
auto compos1 = compose (f, g, l1, g, h, h, l1, l2);
auto compos2 = compose (compos1, l1, l2, fu);
auto x = compos2 (3);
cout << x << endl;
cout << compos2(3) << endl;
cout << fu(l2(l1(l2(l1(h(h(g(l1(g(f(3))))))))))) << endl;
} // ()
Library part:
// ---------------------------------------------------------
// "library" part
// ---------------------------------------------------------
template<typename F1, typename F2>
class Composite{
private:
F1 f1;
F2 f2;
public:
Composite(F1 f1, F2 f2) : f1(f1), f2(f2) { }
template<typename IN>
decltype(auto) operator() (IN i)
{
return f2 ( f1(i) );
}
};
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename F2>
decltype(auto) compose (F1 f, F2 g) {
return Composite<F1, F2> {f,g};
}
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename... Fs>
decltype(auto) compose (F1 f, Fs ... args)
{
return compose (f, compose(args...));
}
The whole program:
// g++ -std=c++1y composition.cpp
#include <iostream>
using namespace std;
// ---------------------------------------------------------
// "library" part
// ---------------------------------------------------------
template<typename F1, typename F2>
class Composite{
private:
F1 f1;
F2 f2;
public:
Composite(F1 f1, F2 f2) : f1(f1), f2(f2) { }
template<typename IN>
decltype(auto) operator() (IN i)
{
return f2 ( f1(i) );
}
};
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename F2>
decltype(auto) compose (F1 f, F2 g) {
return Composite<F1, F2> {f,g};
}
// ---------------------------------------------------------
// ---------------------------------------------------------
template<typename F1, typename... Fs>
decltype(auto) compose (F1 f, Fs ... args)
{
return compose (f, compose(args...));
}
// ---------------------------------------------------------
// "test" part
// ---------------------------------------------------------
int f(int a) { return 2*a; }
double g(int a) { return a+2.5; }
double h(double a) { return 2.5*a; }
double i(double a) { return 2.5-a; }
class Functor {
double x;
public:
Functor (double x_) : x(x_) { }
double operator() (double a) { return a*x; }
};
// ---------------------------------------------------------
// ---------------------------------------------------------
int main () {
auto l1 = [] (double a) { return a/3; };
auto l2 = [] (double a) { return 3.5+a; };
Functor fu {4.5};
auto compos1 = compose (f, g, l1, g, h, h, l1, l2);
auto compos2 = compose (compos1, l1, l2, fu);
auto x = compos2 (3);
cout << x << endl;
cout << compos2(3) << endl;
cout << fu(l2(l1(l2(l1(h(h(g(l1(g(f(3))))))))))) << endl;
} // ()
Here is a simple c++14 solution (it may probably be re-written to c++11):
#include <iostream>
// base condition
template <typename F>
auto compose(F&& f)
{
return [a = std::move(f)](auto&&... args){
return a(std::move(args)...);
};
}
// recursive composition
// from compose(a, b, c...) to compose(ab, c...)
template <typename F1, typename F2, typename... Fs>
auto compose(F1&& f1, F2&& f2, Fs&&... fs)
{
return compose(
[first = std::move(f1), second = std::move(f2)]
(auto&&... args){
return second(first(std::move(args)...));
},
std::move(fs)...
);
}
Possible usage:
int main()
{
const auto f = compose(
[](const auto n){return n * n;},
[](const auto n){return n + 2;},
[](const auto n){return n + 2;}
);
std::cout << f(10) << std::endl; // outputs 104
}
Here is a link to the repo with a few more examples: https://github.com/nestoroprysk/FunctionComposition
A quick implementation of function iteration with argument forwarding. The helper type is unfortunately necessary because function templates can’t be partially specialised.
#include <functional>
#include <iostream>
using namespace std;
template<int n, typename A>
struct iterate_helper {
function<A(A)> f;
iterate_helper(function<A(A)> f) : f(f) {}
A operator()(A&& x) {
return f(iterate_helper<n - 1, A>(f)(forward<A>(x)));
};
};
template<typename A>
struct iterate_helper<1, A> {
function<A(A)> f;
iterate_helper(function<A(A)> f) : f(f) {}
A operator()(A&& x) {
return f(forward<A>(x));
};
};
template<int n, typename A>
function<A(A)> iterate(function<A(A)> f) {
return iterate_helper<n, A>(f);
}
int succ(int x) {
return x + 1;
}
int main() {
auto add5 = iterate<5>(function<int(int)>(succ));
cout << add5(10) << '\n';
}
You haven't shown the body of F, but if you can modify it so that it mutates the input to form the output then change the signature to:
void F(std::vector<uint8_t>& x);
Thereafter you can implement Fn as:
void Fn(std::vector<uint8_t>& x, size_t n)
{
for (size_t i = 0; i < n; i++)
F(x);
}
The compiler will unroll the loop for you if it is more efficient, but even if it doesn't an increment/compare of a local variable will be orders of magnitude faster than calling F.
You can then explcitly copy-construct new vectors when you actually want to make a copy:
vector<uint8_t> v1 = ...;
vector<uint8_t> v2 = v1; // explicitly take copy
Fn(v2,10);
What about (untested):
template < typename Func, typename T >
T compose_impl( Func &&, T &&x, std::integral_constant<std::size_t, 0> )
{ return std::forward<T>(x); }
template < typename Func, typename T, std::size_t N >
T compose_impl( Func &&f, T &&x, std::integral_constant<std::size_t, N> )
{
return compose_impl( std::forward<Func>(f),
std::forward<Func>(f)(std::forward<T>( x )),
std::integral_constant<std::size_t, N-1>{} );
}
template < std::size_t Repeat = 1, typename Func, typename T >
T compose( Func &&f, T &&x )
{
return compose_impl( std::forward<Func>(f), std::forward<T>(x),
std::integral_constant<std::size_t, Repeat>{} );
}
We can use variadic function templates for multiple functions (untested):
template < typename Func, typename T >
constexpr // C++14 only, due to std::forward not being constexpr in C++11
auto chain_compose( Func &&f, T &&x )
noexcept( noexcept(std::forward<Func>( f )( std::forward<T>(x) )) )
-> decltype( std::forward<Func>(f)(std::forward<T>( x )) )
{ return std::forward<Func>(f)(std::forward<T>( x )); }
template < typename Func1, typename Func2, typename Func3, typename ...RestAndT >
constexpr // C++14 only, due to std::forward
auto chain_compose( Func1 &&f, Func2 &&g, Func3 &&h, RestAndT &&...i_and_x )
noexcept( CanAutoWorkHereOtherwiseDoItYourself )
-> decltype( auto ) // C++14 only
{
return chain_compose( std::forward<Func1>(f),
chain_compose(std::forward<Func2>( g ), std::forward<Func3>( h ),
std::forward<RestAndT>( i_and_x )...) );
}
The upcoming decltype(auto) construct automatically computes the return type from an inlined function. I don't know if there's a similar automatic computation for noexcept