Related
What's the correct way to write a specialization for an empty argument variadic template. Take bellow code as an example:
#include <iostream>
#include <memory>
#include <tuple>
#include <functional>
#include <cassert>
using namespace std;
struct message {
int type;
};
struct X: message {
int payload;
X(): message{1} {
}
};
struct Y: message {
int payload;
Y(): message{2} {
}
};
struct Z: message {
int payload;
Z(): message{3} {
}
};
template<typename T>
constexpr int message_type = -1;
template<>
constexpr int message_type<X> = 1;
template<>
constexpr int message_type<Y> = 2;
template<>
constexpr int message_type<Z> = 3;
struct M {
int payload;
M(int payload): payload{ payload } {
}
};
template<typename P, typename T1, typename... Ts>
tuple<int, unique_ptr<M>> helper(unique_ptr<message> &msg, function<int(unique_ptr<T1>&)> fn1, function<int(unique_ptr<Ts>&)>... fn) {
if (msg->type == message_type<T1>) {
unique_ptr<T1> m(static_cast<T1*>(msg.release()));
auto result = fn1(m);
return {result, make_unique<M>(m->payload)};
} else {
return helper<void, Ts...>(msg, fn...);
}
}
template<typename P>
tuple<int, unique_ptr<M>> helper(unique_ptr<message> &msg) {
assert(false);
return {0, unique_ptr<M>()};
}
template<typename... Ts>
tuple<int, unique_ptr<M>> dispatch_msg(unique_ptr<message> &msg, function<int(unique_ptr<Ts>&)> ...fn) {
return helper<void, Ts...>(msg, fn...);
}
int main() {
auto *real_message = new Z;
real_message->payload = 101;
unique_ptr<message> msg(real_message);
auto [result, m] = dispatch_msg<X, Y, Z>(msg, [](auto &x) {
return x->payload + 1;
}, [](auto &y) {
return y->payload + 2;
}, [](auto &z) {
return z->payload + 3;
});
cout << result << '\n' << m->payload << endl;
return 0;
}
The helper function takes variadic template arguments. If it checked all given type arguments and failed. e.g. run to the empty arguments. I want to assert and stop the process.
The current code works but I'm wondering is there any straightforward way to write a specialization.
I simplified the core requirements into the code below:
template<typename T, typename... Ts>
void func(int val, T arg, Ts... args) {
if (condition_hold<T>(val)) {
return;
} else {
return func<Ts...>(val, args...);
}
}
template<>
void func(int val) {
assert(false);
}
int main() {
func<int, double, float>(100);
return 0;
}
Basically the func is checking against every given type whether a condition hold for the input val. If all check failed I want to do something, like the assert here. So I wrote a specialization takes empty argument, but this can't compile.
In C++17, you don't need to split parameter packs into head and tail in most cases. Thanks to fold expressions, many operations on packs become much easier.
// Some generic predicate.
template <typename T>
bool condition_hold(T) {
return true;
}
// Make this whatever you want.
void do_something_with(int);
template<typename... Ts>
auto func(int val, Ts... args) {
// Fold expression checks whether the condition is true for all
// elements of the parameter pack.
// Will be true if the parameter pack is empty.
if ((condition_hold(args) && ...))
do_something_with(val);
}
int main() {
// Ts type parameters are deduced to <float, float>.
func(100, 1.f, 2.f);
return 0;
}
To check whether the pack was empty and handle this case specially, you can do:
template<typename... Ts>
auto func(int val, Ts... args) {
if constexpr (sizeof...(Ts) == 0) {
// handle empty pack
}
else {
// handle non-empty pack
}
}
Your specialization couldn't have worked because func<> needs to take at least one parameter. A specialization such as
template<typename T>
void func<T>(int val);
Wouldn't be valid either, because it wold be a partial specialization which is only allowed for classes.
However, if the base template only takes a pack, we can fully specialize it:
template<typename... Ts>
void func(int val, Ts... args);
template<>
void func<>(int val);
How can I get return type for any function passed to template?
I don't know how to convert between template<typename T> and template<typename Result, typename Args...>:
template<typename T>
void print_name(T f)
{
static_assert(internal::is_function_pointer<T>::value
|| std::is_member_function_pointer<T>::value,
"T must be function or member function pointer.");
typename decltype(f(...)) Result; // ???
typename std::result_of<T>()::type Result; // ???
printf("%s\n", typeid(Result).name());
}
void f_void() {}
int f_int(int x) { return 0; }
float f_float(int x, int y) { return 0.f; }
struct X { int f(int x, float y) { return 0; } };
int main()
{
print_name(f_void);
print_name(f_int);
print_name(f_float);
print_name(&X::f);
return 0;
}
How can i get type Result inside function print_name?
A possible solution is using a function declaration that extracts the return type as well as all the parameters. You don't have even to define it.
It follows a minimal, working example:
#include<typeinfo>
#include<cstdio>
template<typename R, typename... A>
R ret(R(*)(A...));
template<typename C, typename R, typename... A>
R ret(R(C::*)(A...));
template<typename T>
void print_name(T f)
{
printf("%s\n", typeid(decltype(ret(f))).name());
}
void f_void() {}
int f_int(int x) { return 0; }
float f_float(int x, int y) { return 0.f; }
struct X { int f(int x, float y) { return 0; } };
int main()
{
print_name(f_void);
print_name(f_int);
print_name(f_float);
print_name(&X::f);
return 0;
}
As you can see, the declarations provided for ret has the same return type of the submitted function or member function.
A decltype does the rest.
as of C++ 20, the answer is
std::invoke_result_t<T>
If I have a struct like:
struct Thing
{
int x;
int y;
bool a;
bool b;
}
Then I can create a Thing object by doing: Thing t {1,2,true,false};. However, if I have a tuple then I am doing something like:
std::tuple<int, int, bool, bool> info = std::make_tuple(1,2,true,false);
Thing t { std::get<0>(info), std::get<1>(info).. // and so on
Is there a better way to do this?
We can create a generic factory function for creating aggregates from tuple-like types (std::tuple, std::pair, std::array, and arbitrary user-defined tuple-like objects in a structured bindings world†):
template <class T, class Tuple, size_t... Is>
T construct_from_tuple(Tuple&& tuple, std::index_sequence<Is...> ) {
return T{std::get<Is>(std::forward<Tuple>(tuple))...};
}
template <class T, class Tuple>
T construct_from_tuple(Tuple&& tuple) {
return construct_from_tuple<T>(std::forward<Tuple>(tuple),
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{}
);
}
which in your case would be used as:
std::tuple<int, int, bool, bool> info = std::make_tuple(1,2,true,false);
Thing t = construct_from_tuple<Thing>(info); // or std::move(info)
This way, Thing can still be an aggregate (don't have to add constructor/assignments), and our solution solves the problem for many, many types.
As an improvement, we could add SFINAE to both overloads to ensure that they're not callable with invalid tuple types.
†Pending accepting wording of how decomposition will work, the qualified call to std::get<Is> may need to be changed to an unqualified call to get<Is> which has special lookup rules. For now, this is moot, since it's 2016 and we don't have structured bindings.
Update: In C++17, there is std::make_from_tuple().
If you are using c++14 you could make use of std::index_sequence creating helper function and struct as follows:
#include <tuple>
#include <utility>
struct Thing
{
int x;
int y;
bool a;
bool b;
};
template <class Thi, class Tup, class I = std::make_index_sequence<std::tuple_size<Tup>::value>>
struct Creator;
template <class Thi, class Tup, size_t... Is>
struct Creator<Thi, Tup, std::index_sequence<Is...> > {
static Thi create(const Tup &t) {
return {std::get<Is>(t)...};
}
};
template <class Thi, class Tup>
Thi create(const Tup &t) {
return Creator<Thi, Tup>::create(t);
}
int main() {
Thing thi = create<Thing>(std::make_tuple(1,2,true,false));
}
And the version without additional class (with one additional function):
#include <tuple>
#include <utility>
struct Thing
{
int x;
int y;
bool a;
bool b;
};
template <class Thi, class Tup, size_t... Is>
Thi create_impl(const Tup &t, std::index_sequence<Is...>) {
return {std::get<Is>(t)...};
}
template <class Thi, class Tup>
Thi create(const Tup &t) {
return create_impl<Thi, Tup>(t, std::make_index_sequence<std::tuple_size<Tup>::value>{});
}
int main() {
Thing thi = create<Thing>(std::make_tuple(1,2,true,false));
}
Yet another this time tricky version with just one helper function:
#include <tuple>
#include <utility>
struct Thing
{
int x;
int y;
bool a;
bool b;
};
template <class R, class T, size_t... Is>
R create(const T &t, std::index_sequence<Is...> = {}) {
if (std::tuple_size<T>::value == sizeof...(Is)) {
return {std::get<Is>(t)...};
}
return create<R>(t, std::make_index_sequence<std::tuple_size<T>::value>{});
}
int main() {
Thing thi = create<Thing>(std::make_tuple(1,2,true,false));
}
You may use std::tie:
Thing t;
std::tie(t.x, t.y, t.a, t.b) = info;
Here are other ways:
struct Thing
{
Thing(){}
Thing(int A_, int B_, int C_, int D_) //1
: A(A_), B(B_), C(C_), D(D_) {}
Thing(std::tuple<int,int,bool,bool> tuple) //3
: A(std::get<0>(tuple)), B(std::get<1>(tuple)),
C(std::get<2>(tuple)), D(std::get<3>(tuple)) {}
void tie_from_tuple(std::tuple<int,int,bool,bool> tuple) //4
{
std::tie(A,B,C,D) = tuple;
}
int A;
int B;
bool C;
bool D;
};
inline Thing tuple_to_thing(const std::tuple<int,int,bool,bool>& tuple) //2
{
return Thing{std::get<0>(tuple), std::get<1>(tuple),
std::get<2>(tuple), std::get<3>(tuple)};
}
int main()
{
auto info = std::make_tuple(1,2,true,false);
//1 make a constructor
Thing one(info);
//2 make a conversion function
Thing second = tuple_to_thing(info);
//3 don't use tuple (just use the struct itself if you have to pass it)
Thing three{1,2,true,false};
//4 make member function that uses std::tie
Thing four;
four.tie_from_tuple(info);
}
Provide an explicit constructor and assignment operator:
struct Thing
{
int x;
int y;
bool a;
bool b;
Thing() { }
Thing( int x, int y, bool a, bool b ): x(x), y(y), a(a), b(b) { }
Thing( const std::tuple <int, int, bool, bool> & t )
{
std::tie( x, y, a, b ) = t;
}
Thing& operator = ( const std::tuple <int, int, bool, bool> & t )
{
std::tie( x, y, a, b ) = t;
return *this;
}
};
Hope this helps.
Getting fancy with C++17 template argument deduction and using a proxy object (usage example at bottom):
#include <tuple>
using namespace std;
template <class Tuple>
class FromTuple {
// static constructor, used to unpack argument_pack
template <class Result, class From, size_t... indices>
static constexpr Result construct(index_sequence<indices...>, From&& from_tuple) {
return { get<indices>(forward<
decltype(from_tuple.arguments)>(from_tuple.arguments))... };
}
// used to select static constructor
using Indices = make_index_sequence<
tuple_size_v< remove_reference_t<Tuple> >>;
public:
// construct with actual tuple types only for parameter deduction
explicit constexpr FromTuple(const Tuple& arguments) : arguments(arguments) {}
explicit constexpr FromTuple(Tuple&& arguments) : arguments(move(arguments)) {}
// implicit cast operator delegates to static constructor
template <class Result>
constexpr operator Result() { return construct<Result>(Indices{}, *this); }
private:
Tuple arguments;
};
struct Thing { int x; int y; bool a; bool b; };
int main() {
std::tuple<int, int, bool, bool> info = std::make_tuple(1,2,true,false);
Thing thing0((Thing)FromTuple(info));
Thing thing1{(Thing)FromTuple(info)};
FromTuple from_info(info);
Thing thing2(from_info); // only way to avoid implicit cast operator
Thing thing3{(Thing)from_info};
return 0;
}
This generalizes to any class or struct, not just Thing. Tuple arguments will be passed into the constructor.
Say I have a template declaration like this:
template <class A, class B, class C = A (&)(B)>
How would I make it so that I could have a variable amount of objects of type C? Doing class C ...c = x won't work because variadic template arguments can't have default values. So this is what I've tried:
template <typename T>
struct helper;
template <typename F, typename B>
struct helper<F(B)> {
typedef F (&type)(B);
};
template <class F, class B, typename helper<F(B)>::type ... C>
void f(C ...c) { // error
}
But up to the last part I get error messages. I don't think I'm doing this right. What am I doing wrong here?
I think you can use the following approach. First, some machinery for type traits. This allows you to determine if the types in an argument pack are homogeneous (I guess you want all functions to have the same signature):
struct null_type { };
// Declare primary template
template<typename... Ts>
struct homogeneous_type;
// Base step
template<typename T>
struct homogeneous_type<T>
{
using type = T;
static const bool isHomogeneous = true;
};
// Induction step
template<typename T, typename... Ts>
struct homogeneous_type<T, Ts...>
{
// The underlying type of the tail of the parameter pack
using type_of_remaining_parameters = typename
homogeneous_type<Ts...>::type;
// True if each parameter in the pack has the same type
static const bool isHomogeneous =
is_same<T, type_of_remaining_parameters>::value;
// If isHomogeneous is "false", the underlying type is a fictitious type
using type = typename conditional<isHomogeneous, T, null_type>::type;
};
// Meta-function to determine if a parameter pack is homogeneous
template<typename... Ts>
struct is_homogeneous_pack
{
static const bool value = homogeneous_type<Ts...>::isHomogeneous;
};
Then, some more type traits to figure out the signature of a generic function:
template<typename T>
struct signature;
template<typename A, typename B>
struct signature<A (&)(B)>
{
using ret_type = A;
using arg_type = B;
};
And finally, this is how you would define your variadic function template:
template <typename... F>
void foo(F&&... f)
{
static_assert(is_homogeneous_pack<F...>::value, "Not homogeneous!");
using fxn_type = typename homogeneous_type<F...>::type;
// This was template parameter A in your original code
using ret_type = typename signature<fxn_type>::ret_type;
// This was template parameter B in your original code
using arg_type = typename signature<fxn_type>::arg_type;
// ...
}
Here is a short test:
int fxn1(double) { }
int fxn2(double) { }
int fxn3(string) { }
int main()
{
foo(fxn1, fxn2); // OK
foo(fxn1, fxn2, fxn3); // ERROR! not homogeneous signatures
return 0;
}
Finally, if you need an inspiration on what to do once you have that argument pack, you can check out a small library I wrote (from which part of the machinery used in this answer is taken). An easy way to call all the functions in the argument pack F... f is the following (credits to #MarkGlisse):
initializer_list<int>{(f(forward<ArgType>(arg)), 0)...};
You can easily wrap that in a macro (just see Mark's answer to the link I posted).
Here is a complete, compilable program:
#include <iostream>
#include <type_traits>
using namespace std;
struct null_type { };
// Declare primary template
template<typename... Ts>
struct homogeneous_type;
// Base step
template<typename T>
struct homogeneous_type<T>
{
using type = T;
static const bool isHomogeneous = true;
};
// Induction step
template<typename T, typename... Ts>
struct homogeneous_type<T, Ts...>
{
// The underlying type of the tail of the parameter pack
using type_of_remaining_parameters = typename
homogeneous_type<Ts...>::type;
// True if each parameter in the pack has the same type
static const bool isHomogeneous =
is_same<T, type_of_remaining_parameters>::value;
// If isHomogeneous is "false", the underlying type is a fictitious type
using type = typename conditional<isHomogeneous, T, null_type>::type;
};
// Meta-function to determine if a parameter pack is homogeneous
template<typename... Ts>
struct is_homogeneous_pack
{
static const bool value = homogeneous_type<Ts...>::isHomogeneous;
};
template<typename T>
struct signature;
template<typename A, typename B>
struct signature<A (&)(B)>
{
using ret_type = A;
using arg_type = B;
};
template <typename F>
void foo(F&& f)
{
cout << f(42) << endl;
}
template <typename... F>
void foo(typename homogeneous_type<F...>::type f, F&&... fs)
{
static_assert(is_homogeneous_pack<F...>::value, "Not homogeneous!");
using fxn_type = typename homogeneous_type<F...>::type;
// This was template parameter A in your original code
using ret_type = typename signature<fxn_type>::ret_type;
// This was template parameter B in your original code
using arg_type = typename signature<fxn_type>::arg_type;
cout << f(42) << endl;
foo(fs...);
}
int fxn1(double i) { return i + 1; }
int fxn2(double i) { return i * 2; }
int fxn3(double i) { return i / 2; }
int fxn4(string s) { return 0; }
int main()
{
foo(fxn1, fxn2, fxn3); // OK
// foo(fxn1, fxn2, fxn4); // ERROR! not homogeneous signatures
return 0;
}
template <typename T>
struct helper;
template <typename F, typename B>
struct helper<F(B)> {
typedef F (*type)(B);
};
template<class F, class B>
void f()
{
}
template <class F, class B, typename... C>
void f(typename helper<F(B)>::type x, C... c)
{
std::cout << x(B(10)) << '\n';
f<F,B>(c...);
}
int identity(int i) { return i; }
int half(int i) { return i/2; }
int square(int i) { return i * i; }
int cube(int i) { return i * i * i; }
int main()
{
f<int,int>(identity,half,square,cube);
}
Here's a modified version that can deduce types:
template<class F, class B>
void f(F(*x)(B))
{
x(B());
}
template <class F, class B, typename... C>
void f(F(*x)(B), C... c)
{
f(x);
f<F,B>(c...);
}
int identity(int i) { return i; }
int half(int i) { return i/2; }
int square(int i) { return i * i; }
int cube(int i) { return i * i * i; }
int string_to_int(std::string) { return 42; }
int main()
{
f(identity,half,square,cube);
// f(identity,half,string_to_int);
}
There are a lot of impressive Boost libraries such as Boost.Lambda or Boost.Phoenix which go a long way towards making C++ into a truly functional language. But is there a straightforward way to create a composite function from any 2 or more arbitrary functions or functors?
If I have: int f(int x) and int g(int x), I want to do something like f . g which would statically generate a new function object equivalent to f(g(x)).
This seems to be possible through various techniques, such as those discussed here. Certainly, you can chain calls to boost::lambda::bind to create a composite functor. But is there anything in Boost which easily allows you to take any 2 or more functions or function objects and combine them to create a single composite functor, similar to how you would do it in a language like Haskell?
To anyone stumbling onto this page, there's a great blog post on this subject from bureau14:
http://blog.quasardb.net/function-composition-in-c11/
This takes advantage of the new features in C++ 11 as well as using boost.
Stumbling upon this question, I'd like to point out to anyone who comes across this today that this is possible with a relatively elegant syntax using just the standard library and a few helper classes thanks to decltype, auto, and perfect forwarding.
Defining these two classes:
template <class Arg, class ArgCall, class OuterCall>
class pipe {
private:
ArgCall argcall;
OuterCall outercall;
public:
typedef pipe<Arg, ArgCall, OuterCall> this_type;
pipe(ArgCall ac, OuterCall oc) : argcall(ac), outercall(oc) {}
auto operator()(Arg arg) -> decltype(outercall(argcall(arg))) {
return outercall(argcall(arg));
}
template <class NewCall>
pipe<Arg, this_type, NewCall> operator[](NewCall&& nc) {
return {*this, std::forward<NewCall>(nc)};
}
};
template <class Arg>
class pipe_source {
public:
typedef pipe_source<Arg> this_type;
Arg operator()(Arg arg) {
return arg;
}
template <class ArgCall, class OuterCall>
static pipe<Arg, ArgCall, OuterCall> create(ArgCall&& ac, OuterCall&& oc) {
return {std::forward<ArgCall>(ac), std::forward<OuterCall>(oc)};
}
template <class OuterCall>
pipe<Arg, this_type, OuterCall> operator[](OuterCall&& oc) {
return {*this, std::forward<OuterCall>(oc)};
}
};
A simple program:
int f(int x) {
return x*x;
}
int g(int x) {
return x-2;
}
int h(int x) {
return x/2;
}
int main() {
auto foo = pipe_source<int>::create(f, g);
//or:
auto bar = pipe_source<int>()[g][h];
std::cout << foo(10) << std::endl;
std::cout << bar(10) << std::endl;
return 0;
}
This has the added benefit that once it's in a pipe, as long as the return type is correct you can add another function f to the chain with pipe[f].
Then:
$ g++ test.cpp -o test -std=c++11
$ ./test
98
4
$
I don't know of anything that supports the syntax you wish for currently. However, it would be a simple matter to create one. Simply override * for functors (boost::function<> for example) so that it returns a composite functor.
template < typename R1, typename R2, typename T1, typename T2 >
boost::function<R1(T2)> operator * (boost::function<R1(T2)> const& f, boost::function<R2(T2)> const& g)
{
return boost::bind(f, boost::bind(g, _1));
}
Untested, but I suspect it's close if it doesn't work out of the box.
Template them.
template<typename T1> class FunctorOne {
FunctorOne(T1 newt)
: t(newt) {}
void operator()() {
t();
}
T1 t;
};
template<> class FunctorOne<void> {
void operator()() {
}
};
template<typename T1> class FunctorTwo {
FunctorOne(T1 newt)
: t(newt) {}
void operator()() {
t();
}
T1 t;
};
template<> class FunctorTwo<void> {
void operator()() {
}
};
FunctorOne<FunctorTwo<FunctorOne<FunctorTwo<void>>>>> strangefunctionobject(FunctorTwo(FunctorOne(FunctorTwo()));
Excellent use of typedefs is recommended.
Edit: Whoops. Turns out that type inference in constructors sucks. I'll get back in a minute with something that actually works :P
Even more edit:
If you wanted just functors rather than functionoids, you could just create a new instance, or even just use static functions.
template<typename T1, typename T2> class FunctorOne {
public:
static bool Call() {
T1::Call(T2::Call());
return true;
}
};
template<> class FunctorOne<void, void> {
public:
static bool Call() {
}
};
template<typename T1> class FunctorTwo {
public:
static bool Call() {
T1::Call();
}
};
template<> class FunctorTwo<void> {
public:
static bool Call() {
}
};
bool haicakes = FunctorOne<FunctorTwo<void>, FunctorTwo<void>>::Call();
This assumes that in any given function, you can handle each different signature somewhat manually. Use of decltype could help in this regard with a C++0x compiler.
C++11. No boost. No helper classes. Any amount of arguments. Just std::function and variadic templates.
template <typename F1, typename F2>
struct function_composition_traits : public function_composition_traits<decltype(&F1::operator()), decltype(&F2::operator())>
{};
template <typename ClassType1, typename ReturnType1, typename... Args1, typename ClassType2, typename ReturnType2, typename... Args2>
struct function_composition_traits<ReturnType1(ClassType1::*)(Args1...) const, ReturnType2(ClassType2::*)(Args2...) const>
{
typedef std::function<ReturnType2(Args1...)> composition;
template <typename Func1, typename Func2>
inline static composition compose(const Func1& f1, const Func2& f2) {
return [f1,f2](Args1... args) -> ReturnType2 { return f2(f1(std::forward<Args1>(args)...)); };
}
};
template <typename F1, typename F2>
typename function_composition_traits<F1,F2>::composition compose(const F1& lambda1,const F2& lambda2)
{
return function_composition_traits<F1,F2>::template compose<F1,F2>(lambda1, lambda2);
}
template <typename F, typename... Fs>
auto compose(F f, Fs... fs) -> decltype(compose(f, compose(fs...)))
{
return compose(f, compose(std::forward<Fs>(fs)...));
}
Usage:
auto add = [](int x, int y){ return x+y; };
auto mul = [](int x){ return x*2; };
auto divide = [](int x) { return (double)x / 3.0; };
auto test = compose(add, mul, divide);
cout << "Result: " << test(2,3);
Output:
Result: 3.33333
See this answer https://stackoverflow.com/a/27727236/286335.
Really short, easy and general.