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.
Related
I am trying to write a class similar to std::function, just to learn how it works but I am having problem determining the return type of the function.
I found this from one of the answers here on stack overflow. I am trying to do something similar but It does not work and I do not know why.
template< class Fx >
class function
{
public:
function() = default;
function(Fx* fx)
{
this->fx = fx;
}
template < class... A >
ReturnType operator()(A... args)
{
//return ((*fx)(args), ...); ??
}
private:
template<class F>
struct return_type;
template< class R, class... A>
struct return_type<R(*)(A...)>
{
using type = R;
};
using ReturnType = return_type<Fx>::type;
Fx* fx;
};
int sum(int a, int b) { return a + b; };
int main()
{
function<int(int, int)> mysum{ sum };
mysum(10, 10);
}
It gives me an error on line
using ReturnType = return_type<Fx>::type;
saying incomplete type is not allowed. Why does it not pick the specialized one?
Since Fx is supposed to be a function type, not a function pointer type, so the specialization should be declared as:
template< class R, class... A>
struct return_type<R(A...)>
{
using type = R;
};
Other issues:
Change using ReturnType = return_type<Fx>::type; to using ReturnType = typename return_type<Fx>::type;.
Move the declaration of ReturnType (and definition of return_type) before using it as the return type of operator().
Change return ((*fx)(args), ...); to return (*fx)(args...); in the operator(); i.e. all the arguments are supposed to be passed to fx instead of calling fx multiple times with each argument.
LIVE
BTW: Return type deduction (since C++14) is worthy of consideration too. E.g.
template < class... A >
auto operator()(A... args)
{
return (*fx)(args...);
}
LIVE
You should change your template in the class instantiation:
template <typename R, typename ...Args>
class function {
...
R operator()(Args... args){
return fx(...args)
}
}
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
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.
Hi I am trying to write a delegate class that can take a template argument similar to a standard function signature and create a delegate for a member function pointer as shown below in the main. The code may be oversimplified but that is what I was looking for was a simple and fast solution to this problem with as little overhead as possible. I think this implementation is pretty close to achieving what I want if I can get the type T in the class without runtime polymorphism etc.
template<class T>
struct FastDelegate {};
template<class R, class... Args>
struct FastDelegate<R (Args...)>
{
template <typename T>
FastDelegate(T* t, R (T::*f)(Args...)) : m_t(t), m_f(f) {}
R operator()(Args... p)
{
return (m_t->*m_f)(std::forward<Args>(p)...);
}
T* m_t; // How can I capture T as a type in this partial specialization?
R (T::*m_f)(Args...);
};
struct Test
{
int add ( int x, int y ) { return x+y; }
};
int main ()
{
int x = 5;
int y = 4;
Tester t;
FastDelegate<int (int,int)> d (&t, &Test::calc );
int z = d(x,y);
}
You could capture the objects as a void*, store the member function in random member function type, and have a function restore the necessary types. This approach avoid allocating any memory on the heap. The problematic step is the conversion from a member function of some type to another member function. However, according to 5.2.10 [expr.reinterpret.cast] paragraph 10 this approach can be used safely as long at the member function is cast back to its original type before being used:
[...] The result of this conversion is unspecified, except in the following cases:
converting a prvalue of type “pointer to member function” to a different pointer to member function type and back to its original type yields the original pointer to member value.
Below is an example which implements this approach. Note, however, that it is probably easier to use std::function<R(Args...)> with a suitable lambda as the standard library is likely to implementation an approach like that in the first place.
#include <iostream>
#include <utility>
template<class T>
struct FastDelegate {};
template<class R, class... Args>
struct FastDelegate<R (Args...)>
{
struct dummy {};
template <typename T>
FastDelegate(T* t, R (T::*f)(Args...))
: m_t(t)
, m_f(reinterpret_cast<void (dummy::*)()>(f))
, m_call([](void(dummy::*d)(), void* v, Args... a){
typedef R (T::*mem)(Args...);
T* t = static_cast<T*>(v);
mem f = reinterpret_cast<mem>(d);
return (t->*f)(std::forward<Args>(a)...);
}) {
}
R operator()(Args... p) {
return (this->m_call)(this->m_f, this->m_t, std::forward<Args>(p)...);
}
void* m_t;
void (dummy::*m_f)();
R (*m_call)(void (dummy::*)(), void*, Args...);
};
struct Tester
{
int add ( int x, int y ) {
std::cout << "add(" << x << ", " << y << ")\n";
return x+y;
}
};
int main ()
{
int x = 5;
int y = 4;
Tester t;
FastDelegate<int (int,int)> d (&t, &Tester::add);
int z = d(x,y);
}
You don't need to capture type T, because you can use t->*m_f as a function<R(Args...)>
template<class R, class... Args>
struct FastDelegate<R (Args...)>
{
template <typename T>
FastDelegate(T* t, R (T::*f)(Args...))
: m_f([=](Args... v){ return (t->*f)(std::forward(v)...); }) {}
R operator()(Args... p)
{
return m_f(std::forward<Args>(p)...);
}
std::function<R(Args...)> m_f;
};
If you want to compare 2 FastDelegate instance by comparing t and f, there is still no need for type info, just take raw pointer.
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.