Eliminate redundant template argument in C++ - c++

I'm trying to write a demo that implements the fmap in Haskell with continuation, and my code looks like this:
#include <cstdio>
#include <functional>
template <typename X>
using Callback = std::function<void(X)>;
template <typename X, typename Y>
using Fun = std::function<Y(X)>;
template <typename X, typename Y>
struct F_map;
template <typename X>
struct __F {
virtual void operator()(Callback<X>&& callback) = 0;
virtual __F<X>* self() { return this; }
template <typename Y>
auto map(Fun<X, Y>&& f) { return F_map(self(), f); }
};
template <typename X>
struct F_id : __F<X> {
const X x;
F_id(const X& x) : x(x) {}
__F<X>* self() override { return this; }
void operator()(Callback<X>&& callback) override { callback(x); }
};
template <typename X, typename Y>
struct F_map : __F<Y> {
__F<X>* upstream;
Fun<X, Y> f;
F_map(__F<X>* upstream, const Fun<X, Y>& f) : upstream(upstream), f(f) {}
__F<Y>* self() override { return this; }
void operator()(Callback<Y>&& callback) override {
upstream->operator()([=](X&& x) {
callback(f(x));
});
}
};
int main(int argc, char* argv[]) {
auto f =
F_id(10)
.map<int>([](int x) { return x + 2; })
.map<const char*>([](int x) { return "1, 2, 3"; });
f([](const char* x) { printf("%s\n", x); });
return 0;
}
That works fine, but the map<int> and map<const char*> looks ugly. I think these declarations can be omitted, but if I remove that I got an error message that says "no instance of function template "F_id::map [with X=int]" matches the argument list".
Any idea to remove these template arguments?

There are multiple kinds of polymorphism in C++. By polymorphism, I mean whenever a single variable in code has different implementation types.
There is classic C++ inheritance and virtual based polymorphism. There is type erasure based polymorphism. And there is static polymorphism of templates.
In many senses, these kinds of polymorphism are opposed to each other. If you use one when you should be using the other, it is like using covariance when you should be using contravariance. Your code might stumble along, but it will only work when forced, like taking a square peg and a round hole and a big hammer.
Your <int> requirement is an example of using the wrong kind of polymorphism, and the <int> is the hammer smashing it into the wrong-shaped hole.
You are attempting to use
template <typename X>
using Callback = std::function<void(X)>;
and
template <typename X, typename Y>
using Fun = std::function<Y(X)>;
as pattern matchers. They aren't pattern matchers, even if in specific cases they can be used as pattern matchers. Callback and Fun are a type erasers.
Callback<X> takes anything that can be called with something that can be converted from an X, and stores it. Then forgets almost every other fact about it (well, it remembers how to copy it, its typeid, and a few other random facts).
Fun<X,Y> takes anything that can be called with something that can be converted from an X, and whose return value can then be converted to a Y. It then forgets almost every other fact about it.
Here:
template <typename Y>
auto map(Fun<X, Y>&& f) { return F_map(self(), f); }
you are trying to use it to say "I accept an f. Please find me a Y that would match this f".
This is pattern matching. Type erasure and pattern matching are opposite operations.
This is a really common mistake. With classic inheritance, they sometimes end up being the same thing.
std::function is for forgetting information about something, being able to store it, then later using only the parts you remember.
The first question is, do you need to pattern match, or do you need a type function here?
Probably you are good with a type function.
template <class F, class R = std::invoke_result_t<F, X>>
F_map<X,R> map(F&& f) { return {self(), std::forward<F>(f)}; }
here we map the incoming F to its return value R.
Your code has other issues. Like dangling pointers. Also, it insists on knowing what types the callables use; in C++, you can ... just not bother knowing that.
So, using the CRTP for static polymorphism, and mechanically forgetting what types I work on an replacing them with non-type erased code, I get:
#include <cstdio>
#include <type_traits>
template <class Upstream, class F>
struct F_map;
template<class D>
struct mappable
{
template <class F>
F_map<D, F> map(F const& f) { return F_map(static_cast<D*>(this), f); }
};
template <class Upstream, class F>
struct F_map:
mappable<F_map<Upstream, F>>
{
Upstream* upstream;
F f;
F_map(Upstream* upstream, const F& f) : upstream(upstream), f(f) {}
template<class Callback>
void operator()(Callback&& callback) {
(*upstream)([=](auto&& x) {
callback(f(decltype(x)(x)));
});
}
};
template <typename X>
struct F_id:
mappable<F_id<X>>
{
const X x;
F_id(const X& x) : x(x) {}
template<class Callback>
void operator()(Callback&& callback) { callback(x); }
};
int main(int argc, char* argv[]) {
auto f =
F_id(10)
.map([](int x) { return x + 2; })
.map([](int x) { return "1, 2, 3"; });
f([](const char* x) { printf("%s\n", x); });
return 0;
}
Live example.
I still think you are following dangling pointers, but I am not sure.
The return value of map stores a pointer to the object we call it on, and that object was a temporary destroyed when we made f.
To fix the Upstream* problem, I'd do this:
template <class Upstream, class F>
struct F_map;
template<class D>
struct mappable
{
template <class F>
F_map<D, F> map(F const& f) const { return {*static_cast<D const*>(this), f}; }
};
template <class Upstream, class F>
struct F_map:
mappable<F_map<Upstream, F>>
{
Upstream upstream;
F f;
F_map(Upstream const& upstream, const F& f) : upstream(upstream), f(f) {}
template<class Callback>
void operator()(Callback&& callback) const {
upstream([=](auto&& x) {
callback(f(decltype(x)(x)));
});
}
};
template <typename X>
struct F_id:
mappable<F_id<X>>
{
const X x;
F_id(const X& x) : x(x) {}
template<class Callback>
void operator()(Callback&& callback) const { callback(x); }
};
copy upstream by value.

If you don't want to provide template arguments to __F::map, you can add another map template that accepts an arbitrary callable, and you can use the type of that callable to figure out the return type:
template <typename F> // <-- any function
auto map(F&& f) { return F_map<X, decltype(f(X{}))>(self(), f); }
// ^ ^^^^^^^^^^^^^^^^ argument, and return type
Note that you now need to specify the template parameters to F_map, but you have the needed information to do that, and is not something the caller has to worry about.
Now this call works:
auto f =
F_id(10)
.map([](int x) { return x + 2; })
.map([](int x) { return "1, 2, 3"; });
Here's a demo.
As pointed out by Marek R in a comment, and as apparent from the demo with Clang, you have some bug in your code that causes a run-time error. You should fix that.
Also, as pointed out by Yakk-Adam Nevraumont in a comment, names containing double underscores __ are reserved for the implementation. Don't use such names in your code.

Related

How to have a function template get the parameter types of its lambda argument?

Assume we have a class template like this:
template <typename baseT, typename ...argTs>
class CCallable : public baseT
{
public:
CCallable(std::function<bool(argTs...)> lambda)
: m_lambda(lambda) {
}
bool Invoke(argTs ...args) override {
return m_lambda(args...);
}
private:
std::function<bool(argTs...)> m_lambda;
};
And assume we have a function template callback implemented, probably similar to this pseudo code:
template <typename baseT, typename lambdaT>
CCallable<baseT, typename lambdaT::argTs...> callback(lambdaT lambda)
{
return CCallable<baseT, typename lambdaT::argTs...>(lambda);
}
so that we are able to do this:
auto&& functor = callback<CBase>([](int x, int y, int *sum)->bool{
*sum = x + y;
return true;
});
// Start passing functor around and then...
int sum;
functor.Invoke(7, 42, &sum);
Please note that the parameter types of the lambda are not passed to callback as its template type arguments.
How can we implement a function template like this, to save the users from typing more codes like:
auto&& functor = callback<CBase, int, int, int*>([](int x, int y, int *sum)->bool{
*sum = x + y;
return true;
});
Thanks.
By the way, why I'm asking this is because Microsoft::WRL provides a similar template named Callback which is called many times in an opensource library I want to use. However, I prefer to build the library with GNU C++ instead of Visual C++. Therefore, it seems inevitable that I have to implement a Microsoft::WRL::Callback-like template or macro myself.
With C++17 CTAD, you could harness deduction guides for std::function:
template<class T>
struct Identity { };
template<typename baseT, typename ...argTs>
class CCallable : public baseT {
public:
CCallable(std::function<bool(argTs...)> lambda, Identity<baseT> = {})
: m_lambda(lambda) {
}
bool Invoke(argTs ...args) override {
return m_lambda(args...);
}
private:
std::function<bool(argTs...)> m_lambda;
};
template<typename baseT, typename lambdaT>
auto callback(lambdaT lambda) {
return CCallable(std::function(lambda), Identity<baseT>{});
}
CTAD is all-or-nothing, so the type baseT is wrapped into Identity to make it deducible.
Demo

Generic function that accepts const and non-const data and related function

To make more sence for the question title consider the following code:
template <typename T>
void write(const T& /*data*/)
{
// use data as const
}
template <typename T>
void read(T& /*data*/)
{
// modify data
}
struct S {
int a;
int b;
// a lot of primitive types here
};
void output(const S& s)
{
write(s.a);
write(s.b);
// ...
}
void input(S& s)
{
read(s.a);
read(s.b);
// ...
}
int main()
{
S s;
input(s);
output(s);
}
I have write and read functions that manipulate primitive data like int, double etc. I have several struct types like S that contains a lot of primitive data members, and I need to input and output such types via corresonding functions input and output (there are many of overloads for distinct types). As you can see the content of output and input functions mostly the same, only the inner functions and type constness are different. I would like to make some generic (template) function use to eliminate code duplicates from input/output functions.
I think the template signature will be the following (but I can miss something):
template <typename F, typename T>
void use(T& t) { ... }
So I could call the use function from input/output like this:
use<write, S>(s); // in output function
use<read, S>(s); // in input fuction
How to archive this (or similar) behaviour to eliminate code duplications? I'm using C++14.
template <typename S, typename F>
void use(S&& s, F&& f)
{
f(s.a);
f(s.b);
f(s.c);
}
Usage:
use(s, [](const auto& x){ write(x); });
use(s, [](auto& x) { read(x); });
live example on wandbox.org
If you need multiple types:
template <typename S, typename Target>
using EnableFor = std::enable_if_t<std::is_same_v<std::decay_t<S>, Target>>;
template <typename S, typename F>
auto use(S&& s, F&& f) -> EnableFor<S, S0>
{
f(s.a);
f(s.b);
f(s.c);
}
template <typename S, typename F>
auto use(S&& s, F&& f) -> EnableFor<S, S1>
{
f(s.d);
f(s.e);
f(s.f);
}
Usage:
int main()
{
S0 s0;
use(s0, [](const auto& x){ write(x); });
use(s0, [](auto& x) { read(x); });
S1 s1;
use(s1, [](const auto& x){ write(x); });
use(s1, [](auto& x) { read(x); });
}
live example on wandbox.org
You can define an interface of the template being used:
template<class M, class S>
void use(S &&s) {
M::method(s.a);
M::method(s.b);
};
Then implement it:
template <typename T>
void write(const T& /*data*/)
{
// use data as const
}
struct writer {
template <typename T>
static void method(const T& t)
{
write(t);
}
};
Now you can use it:
use<writer>(s);
For read, it's the same:
struct reader {
template <typename T>
static void method(T& t)
{
read(t);
}
};
use<reader>(s);
I believe I understood what you want, but it is impossible. Currently there is no way to implement in C++ generic streaming for all classes. One would need access to information like number of fields the class has, their relative address as well as type in compile time.
Currently they are working on adding this to C++ for many years, seek Reflection TS. As far as I know it won't be ready for C++20.
However, you can organize your code so that each read/write method is easy to implement. For example:
class A : public B, public C
{
private:
vector<int> m_v;
int m_x;
};
Then implement write for it as
template<>
void write(const A& a)
{
write((const B&)a);
write((const C&)a);
write(a.m_v);
write(a.m_x);
}
While for common data structures like std::vector<T> implement write via write<T>. It takes time but making it technical and using redirections can save a lot of code and time.
(You need to make write a friend function, or a member function to let it access private members)

Passing Template Variable to Template Function in C++14

I'm writing a compiler that compiles to C++ and am having type issues with my C++ code. The language is meant to be lazy, so we have a lazy value wrapper, Chunk. Here is a part of it, along with the problematic code:
#include <functional>
#include <memory>
template<class T>
class Chunk
{
public:
Chunk();
Chunk(std::function<T()> f);
T operator()();
std::function<T()> f_;
private:
std::shared_ptr<T> cache_;
};
template<class T>
T Chunk<T>::operator()()
{
if(cache_ == nullptr)
cache_ = std::make_shared<T>(f_());
return *cache_;
}
template<class T, class F>
T operator*(Chunk<T> t1, Chunk<F> t2)
{
return t1() * t2();
}
template<class T, class... Args>
T apply(Chunk<std::function<T(Args...)>> c, Args... as)
{
return c()(as...);
}
template<class F>
auto toChunk(F f) -> Chunk<decltype(f())>
{
return Chunk<decltype(f())>(f);
}
template<class T, class F>
struct ops
{
static const auto multiply =
toChunk([]() { return ops::multiply_; });
static const auto multiply_(Chunk<T> x, Chunk<F> y) -> decltype(x * y)
{
return x * y;
}
};
int main()
{
Chunk<double> t = toChunk([]() { return 1.0; });
Chunk<float> f = toChunk([]() { return 2.0f; });
apply(ops::multiply, t, f);
return 0;
}
I can't figure out a definition of multiply to make this work without getting a used without template parameters error. (There may be a second issue here because multiply_ isn't a std::function, but the compiler breaks on the lack of template parameters first.)
I could write a lot of overloads for every pair of types, but this is just really ugly. I tried making multiply a template variable without a template class, and even though I'm using C++14, got cannot resolve address of overloaded function at multiply_ with this alternative definition:
template<class T, class F>
auto multiply_(Chunk<T> x, Chunk<F> y) -> decltype(x * y)
{
return x * y;
}
template<class T, class F>
Chunk<decltype(multiply_)> multiply = toChunk([]() { return multiply_; });
Of course I then changed ops::multiply to simply multiply. Any suggestions to overcome this?
ops is a name of a class template. To refer to members of a class template outside of its definition you need to specify the template arguments.
If you fix this error though, there are going to be more.
I ended up using an entirely different solution. I overloaded apply by adding this second definition:
template<class F, class... Args>
auto apply(F f, Args... as) -> decltype(f(as...))
{
return f(as...);
}
And rewrote multiply as simply:
auto multiply = [](auto x, auto y) { return x * y; };
So our library functions will not be in the lazy wrappers, while user-defined functions (which can't be templates in our language) will.

How std::function works

You know, we can wrap or store a lambda function to a std::function:
#include <iostream>
#include <functional>
int main()
{
std::function<float (float, float)> add = [](float a, float b)
// ^^^^^^^^^^^^^^^^^^^^
{
return a + b;
};
std::cout << add(1, 2) << std::endl;
}
My question is around std::function, as you can see it is a template class but it can accept any kind of function signature.
For example float (float, float) in this form return_value (first_arg, second_arg).
What's the structure of std::function and how does it accept a function signature like x(y,z) and how it works with it? Is float (float, float) a new valid expression in C++?
It uses some type erasure technique.
One possibility is to use mix subtype polymorphism with templates. Here's a simplified version, just to give a feel for the overall structure:
template <typename T>
struct function;
template <typename Result, typename... Args>
struct function<Result(Args...)> {
private:
// this is the bit that will erase the actual type
struct concept {
virtual Result operator()(Args...) const = 0;
};
// this template provides us derived classes from `concept`
// that can store and invoke op() for any type
template <typename T>
struct model : concept {
template <typename U>
model(U&& u) : t(std::forward<U>(u)) {}
Result operator()(Args... a) const override {
t(std::forward<Args>(a)...);
}
T t;
};
// this is the actual storage
// note how the `model<?>` type is not used here
std::unique_ptr<concept> fn;
public:
// construct a `model<T>`, but store it as a pointer to `concept`
// this is where the erasure "happens"
template <typename T,
typename=typename std::enable_if<
std::is_convertible<
decltype( t(std::declval<Args>()...) ),
Result
>::value
>::type>
function(T&& t)
: fn(new model<typename std::decay<T>::type>(std::forward<T>(t))) {}
// do the virtual call
Result operator()(Args... args) const {
return (*fn)(std::forward<Args>(args)...);
}
};
(Note that I overlooked several things for the sake of simplicity: it cannot be copied, and maybe other problems; don't use this code in real code)

Function Composition in C++

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.