- Why is this ever interesting? It could be implemented in terms of
__gnu_cplusplus_builtin_std_function__
for all we know.
- No, the standard explicitly permits that.
- Definitely yes, with any number of fully standard-conforming techniques.
The rest of the question is ill-posed, addressed in a comment.
Here's a rudimentary mock-up of std::function
on the back of an envelope, with no casts or unions or AFAICT anything remotely dangerous. Of course not all features of real std::function
either, but that's just a matter of some technical work.
#include <memory>
#include <iostream>
#include <type_traits>
template <typename R, typename ... Args>
struct CallBase
{
virtual R operator()(Args... args) = 0;
virtual ~CallBase() {}
};
template <typename R, typename ... Args>
struct FunCall : CallBase<R, Args...>
{
virtual R operator()(Args... args) { return f(args...); }
R(*f)(Args...);
FunCall(R f(Args...)) : f(f) {}
};
template <typename Obj, typename R, typename ... Args>
struct ObjCall : CallBase<R, Args...>
{
virtual R operator()(Args... args) { return o(args...); }
Obj o;
ObjCall(Obj o) : o(o) {}
};
template <typename R, typename ... Args> struct MemFunCall;
template <typename R, typename Cl, typename ... Args>
struct MemFunCall<R, Cl, Args...> : CallBase<R, Cl, Args...>
{
typedef typename std::remove_reference<Cl>::type Rcl;
virtual R operator()(Cl c, Args... args) { return (c.*f)(args...); }
R (Rcl::*f)(Args...);
MemFunCall(R (Rcl::*f)(Args...)) : f(f) {}
};
template <typename Fn> class Function;
template <typename R> struct Function<R()>
{
std::unique_ptr<CallBase<R>> fn;
R operator()() { return (*fn)(); }
Function(R (*f)()) : fn(new FunCall<R>(f)) {}
template<typename Obj>
Function(Obj o) : fn(new ObjCall<Obj, R>(o)) {}
};
template <typename R, typename Arg1, typename ... Args>
struct Function<R(Arg1, Args...)>
{
std::unique_ptr<CallBase<R, Arg1, Args...>> fn;
R operator()(Arg1 arg1, Args... args) { return (*fn)(arg1, args...); }
Function(R (*f)(Arg1 arg1, Args...)) :
fn(new FunCall<R, Arg1, Args...>(f)) {}
template<typename T>
Function(R (T::*f)(Args...)) :
fn(new MemFunCall<R, Arg1, Args...>(f)) {}
template<typename Obj>
Function(Obj o) : fn(new ObjCall<Obj, R, Arg1, Args...>(o)) {}
};
struct Foo
{
static void bar (int a) { std::cout << "bar " << a << std::endl; }
int baz (const char* b) { std::cout << "baz " << b << std::endl; return 0; }
void operator()(double x) { std::cout << "operator() " << x << std::endl; }
};
int main ()
{
Function<void(int)> f1(&Foo::bar);
f1(3);
Foo foo;
Function<int(Foo&, const char*)> f2(&Foo::baz);
f2(foo, "whatever");
Function<void(double)> f3(foo);
f3(2.75);
}