Mimic std::function template arguments - c++

I'm want to mimic std::function template arguments but I don't know how it really works.
Consider this code for example:
std::function<int(int)> p;
How do I write class template that mimics this template parameter <int(int)> ?
template<typename ...> <-- what should be here instead of `...`
MyClass
What I'm really trying to achieve is that I want to be able to typedef <int(int)> as function pointer and I want it to be generic not only for int (*func)(int) functions.
I'm trying to achieve something like this:
SomeSmartStruct<MyClass, int(int)>::MemFuncPointerType pMemFunc;
I want MemFuncPointerType to be of the following type:
int (__thiscall MyClass::* )(int)
And:
SomeSmartStruct<MyClass, int(int)>::FunctionPointer pFunc;
should be of this type:
int (__cdecl *)(int)
I'm using VS2010 so not all C++11 features are supported but it does implements std::function.

With variadic templates:
template <typename C, typename T>
struct make_member_function_pointer;
template <typename C, typename R, typename... Args>
struct make_member_function_pointer<C,R(Args...)>
{
using type = R(C::*)(Args...);
};
DEMO 1
Without variadic templates:
template <typename T> struct identity { typedef T type; };
template <typename C, typename T>
struct make_member_function_pointer;
template <typename C, typename R, typename Arg1>
struct make_member_function_pointer<C,R(Arg1)> : identity<R(C::*)(Arg1)> {};
template <typename C, typename R, typename Arg1, typename Arg2>
struct make_member_function_pointer<C,R(Arg1,Arg2)> : identity<R(C::*)(Arg1,Arg2)> {};
template <typename C, typename R, typename Arg1, typename Arg2, typename Arg3>
struct make_member_function_pointer<C,R(Arg1,Arg2,Arg3)> : identity<R(C::*)(Arg1,Arg2,Arg3)> {};
DEMO 2
Usage:
template <typename T, typename F>
struct SomeSmartStruct
{
typedef typename make_member_function_pointer<T,F>::type MemFuncPointerType;
typedef F* FunctionPointer;
};
Tests:
struct MyClass
{
int foo(int) {return 0;}
};
int bar(int) {return 0;}
int main()
{
SomeSmartStruct<MyClass, int(int)>::MemFuncPointerType pMemFunc = &MyClass::foo;
SomeSmartStruct<MyClass, int(int)>::FunctionPointer pFunc = &bar;
}
UPDATE
Can I somehow utilize the preprocessor to auto generate partial specializations of make_member_function_pointer? I've seen something similar is done using BOOST_PP_ITERATION but I don't know how it works.
Sure:
#include <boost/preprocessor.hpp>
template <typename T> struct identity { typedef T type; };
template <typename C, typename T>
struct make_member_function_pointer;
#define BOOST_PP_LOCAL_MACRO(n)\
template <typename C, typename R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Arg)>\
struct make_member_function_pointer<C,R(BOOST_PP_ENUM_PARAMS(n, Arg))> : identity<R(C::*)(BOOST_PP_ENUM_PARAMS(n, Arg))> {};
#define BOOST_PP_LOCAL_LIMITS (0, 20) // 20 is the limit of params
#include BOOST_PP_LOCAL_ITERATE()
Tests:
int bar10(int,int,int,int,int,int,int,int,int,int) {return 0;}
SomeSmartStruct<MyClass, int(int,int,int,int,int,int,int,int,int,int)>::FunctionPointer pFunc10 = &bar10;
DEMO 3

int(int) is just a type so can be matched by template <typename T>.
Surely too generic:
template<typename T>
struct Pointer
{
typedef T* type;
};
And then you may do
int foo(int i) {return i;}
int main() {
Pointer<int(int)>::type f = &foo;
}

Related

C++: How do I find out the return type of a function? [duplicate]

basically how to make following code compile?
I know it failed because compiler was trying to evaluate something like ([](int &i){})(0) but how to solve the problem?
template <class TElement>
struct foo {
TElement _e;
foo(TElement e) : _e(e){}
template <class Lambda>
void bar(Lambda f) {
using TResult = decltype(std::declval<Lambda>()(std::declval<TElement>()));
}
};
int main() {
foo<int>(0).bar([](int i){}); // compile
foo<int>(0).bar([](int &&i){}); // compile
foo<int>(0).bar([](int const &i){}); // compile
foo<int>(0).bar([](int &i){}); // failed
}
You may use following traits:
template <typename T>
struct return_type : return_type<decltype(&T::operator())>
{};
// For generic types, directly use the result of the signature of its 'operator()'
template <typename ClassType, typename ReturnType, typename... Args>
struct return_type<ReturnType(ClassType::*)(Args...) const>
{
using type = ReturnType;
};
Two ways. First:
using TResult = decltype(f(_e));
or second:
using TResult = typename std::result_of<Lambda&(TElement&)>::type;
Your code implicity says that the TElement is a temprary/rvalue. The & above makes them lvalues.
You might resolve it with:
template <typename Lambda, typename T>
struct lambda_return_type {
private:
template<typename U>
static constexpr auto check(U*) -> decltype(std::declval<Lambda>()(std::declval<U>()));
template<typename U>
static constexpr auto check(...) -> decltype(std::declval<Lambda>()(std::declval<U&>()));
public:
typedef decltype(check<T>(nullptr)) type;
};
and
void bar(Lambda f) {
typedef typename lambda_return_type<Lambda, TElement>::type TResult;
}

How to create template class with member function pointer?

Is anyone knows how to declare generalized template form for the next template specialization:
template <template <class> class Container,
class Value,
class Return,
Return (Container<Value>::*Apply)(const Value &)>
class Example<Container<Value>, Apply>
{
};
Apply must be a pointer to a member function whoes signature is unknown in template declaration.
Do you mean something like this?
template<typename T, typename F>
struct S;
template<template <typename...> class C, typename R, typename... A>
struct S<C<A...>, R(A...)> {
using Apply = R(C<A...>::*)(A...);
// ...
};
As an example:
template<typename... U>
struct T {
int f(int, char) { return 42; }
};
template<typename T, typename F>
struct S;
template<template <typename...> class C, typename R, typename... A>
struct S<C<A...>, R(A...)> {
using Apply = R(C<A...>::*)(A...);
// ...
};
int main() {
S<T<int, char>, int(int, char)>::Apply apply = &T<int, char>::f;
}
Pretty ugly, indeed, but that's what the OP (maybe) asked.

C++ deduce member function parameters

I'm looking to extend the functionality described here but for member functions, what would be the syntax in this case?
Also, the (*) in the template definition, is that de-referencing the function pointer so the compiler can deduce the template arguments?
Would appreciate any input!
Thanks
template <class F> struct ArgType;
template <class R, class T>
struct ArgType<R(*)(T)> {
typedef T type;
};
void f(int) {}
#include <type_traits>
#include <iostream>
int main() {
// To prove
std::cout << std::is_same< ArgType<decltype(&f)>::type, int >::value << '\n';
// To use
ArgType<decltype(&f)>::type a;
}
Pointer-to-members look like Ret (Cls::*)(Args...) [cv-qualifiers] [ref-qualifiers]. So you can extend your class to deduce the first type thusly:
template <class F> struct ArgType;
template <typename Ret, typename Cls, typename T, typename... Args>
struct ArgType<Ret (Cls::*)(T, Args...)> {
using type = T;
};
Note that you can make this more generic by write a metafunction that gives you the nth argument:
template <typename Ret, typename Cls, typename... Args>
struct ArgType<Ret (Cls::*)(Args...)> {
template <size_t N>
struct get_arg {
using type = typename std::tuple_element<N,
std::tuple<Args...>>::type;
};
};
So ArgType<F>::arg<0>::type would be the type you seek.

Determining number and type of parameters and return type of type parameter that is a function

Given a C++11 function:
X f(A, B, C);
Is there anyway from within this function:
template<typename T>
void g(T t)
{
...
}
Called as follows:
g(f);
to determine:
the number of parameters of f
the type of parameter i of f
the return type of f
...
template<typename F>
void g(F f)
{
constexpr size_t n = num_params<F>::n; // 3
return_type<F>::type x; // X
tuple<param_types<F>::type...> a; // tuple<A, B, C>
}
?
Sure:
template <typename R, typename ...Args>
void g(R(&f)(Args...))
{
typedef R return_type;
unsigned int const n_args = sizeof...(Args);
// ...
}
Usage:
int foo(char, bool);
g(foo);
Something I had worked on that does what you want I think -- it is however limited to functors that define at most one function call operator (lambdas fit this restriction). It also works on MSVC 2012 CTP.
namespace detail {
////////////////////////////////////////////////////////////////////////////
//! Select between function pointer types
////////////////////////////////////////////////////////////////////////////
template <typename T>
struct callable_helper_ptr;
//! non-member functions
template <typename R, typename... Args>
struct callable_helper_ptr<R (*)(Args...)> {
typedef void object_t;
typedef R result_t;
typedef std::tuple<Args...> args_t;
};
//! member functions
template <typename R, typename O, typename... Args>
struct callable_helper_ptr<R (O::*)(Args...)> {
typedef O object_t;
typedef R result_t;
typedef std::tuple<Args...> args_t;
};
//! const member functions
template <typename R, typename O, typename... Args>
struct callable_helper_ptr<R (O::*)(Args...) const> {
typedef O object_t;
typedef R result_t;
typedef std::tuple<Args...> args_t;
};
////////////////////////////////////////////////////////////////////////////
//! Select between function pointers and functors
////////////////////////////////////////////////////////////////////////////
template <typename T, typename is_ptr = typename std::is_pointer<T>::type>
struct callable_helper;
//! specialization for functors (and lambdas)
template <typename T>
struct callable_helper<T, std::false_type> {
typedef callable_helper_ptr<decltype(&T::operator())> type;
};
//! specialization for function pointers
template <typename T>
struct callable_helper<T, std::true_type> {
typedef callable_helper_ptr<T> type;
};
} //namespace detail
////////////////////////////////////////////////////////////////////////////////
//! defines the various details of a callable object T
////////////////////////////////////////////////////////////////////////////////
template <typename T>
struct callable_traits {
typedef typename detail::callable_helper<T>::type::object_t object_t;
typedef typename detail::callable_helper<T>::type::result_t result_t;
typedef typename detail::callable_helper<T>::type::args_t args_t;
template <unsigned N>
struct arg : public std::tuple_element<N, args_t> {};
};
And my write up on the process behind writing if anyone is interested:
http://bkentel.wordpress.com/2012/12/12/defining-a-traits-type-for-callable-objects/

detecting typedef at compile time (template metaprogramming)

I am currently doing some template metaprogramming. In my case I can handle any "iteratable" type, i.e. any type for which a typedef foo const_iterator exists in the same manner. I was trying to use the new C++11 template metaprogramming for this, however I could not find a method to detect if a certain type is missing.
Because I also need to turn on/off other template specializations based on other characteristics, I am currently using a template with two parameters, and the second one gets produced via std::enable_if. Here is what I am currently doing:
template <typename T, typename Enable = void>
struct Foo{}; // default case is invalid
template <typename T>
struct Foo< T, typename std::enable_if<std::is_fundamental<T>::value>::type>{
void do_stuff(){ ... }
};
template<typename T>
struct exists{
static const bool value = true;
};
template<typename T>
struct Foo<T, typename std::enable_if<exists< typename T::const_iterator >::value >::type> {
void do_stuff(){ ... }
};
I was not able to do something like this without the exists helper template. For example simply doing
template<typename T>
struct Foo<T, typename T::const_iterator> {
void do_stuff(){ ... }
};
did not work, because in those cases where this specialization should be used, the invalid default case was instantiated instead.
However I could not find this exists anywhere in the new C++11 standard, which as far as I know simply is taking from boost::type_traits for this kind of stuff. However on the homepage for boost::type_traits does not show any reference to anything that could be used instead.
Is this functionality missing, or did I overlook some other obvious way to achieve the desired behavior?
If you simply want if a given type contains const_iterator then following is a simplified version of your code:
template<typename T>
struct void_ { typedef void type; };
template<typename T, typename = void>
struct Foo {};
template<typename T>
struct Foo <T, typename void_<typename T::const_iterator>::type> {
void do_stuff(){ ... }
};
See this answer for some explanation of how this technique works.
You can create a trait has_const_iterator that provides a boolean value and use that in the specialization.
Something like this might do it:
template <typename T>
struct has_const_iterator {
private:
template <typename T1>
static typename T1::const_iterator test(int);
template <typename>
static void test(...);
public:
enum { value = !std::is_void<decltype(test<T>(0))>::value };
};
And then you can specialize like this:
template <typename T,
bool IsFundamental = std::is_fundamental<T>::value,
bool HasConstIterator = has_const_iterator<T>::value>
struct Foo; // default case is invalid, so no definition!
template <typename T>
struct Foo< T, true, false>{
void do_stuff(){// bla }
};
template<typename T>
struct Foo<T, false, true> {
void do_stuff(){//bla}
};
Here's another version of a member type trait check:
template<typename T>
struct has_const_iterator
{
private:
typedef char yes;
typedef struct { char array[2]; } no;
template<typename C> static yes test(typename C::const_iterator*);
template<typename C> static no test(...);
public:
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
There is a couple of ways to do this. In C++03, you could use boost and enable_if to define the trait (docs, source):
BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator);
template <typename T, typename Enable = void>
struct Foo;
template <typename T>
struct Foo< T, typename boost::enable_if<boost::is_fundamental<T> >::type>{
void do_stuff(){ ... }
};
template<typename T>
struct Foo<T, typename boost::enable_if<has_const_iterator<T> >::type> {
void do_stuff(){ ... }
};
In C++11, you could use Tick like this:
TICK_TRAIT(has_const_iterator)
{
template<class T>
auto require(const T&) -> valid<
has_type<typename T::const_iterator>
>;
};
template <typename T, typename Enable = void>
struct Foo;
template <typename T>
struct Foo< T, TICK_CLASS_REQUIRES(std::is_fundamental<T>::value)>{
void do_stuff(){ ... }
};
template<typename T>
struct Foo<T, TICK_CLASS_REQUIRES(has_const_iterator<T>())> {
void do_stuff(){ ... }
};
Also with Tick you can further enhance the trait to actually detect that the const_iterator is actually an iterator, as well. So say we define a simple is_iterator trait like this:
TICK_TRAIT(is_iterator,
std::is_copy_constructible<_>)
{
template<class I>
auto require(I&& i) -> valid<
decltype(*i),
decltype(++i)
>;
};
We can then define has_const_iterator trait to check that the const_iterator type matches the is_iterator trait like this:
TICK_TRAIT(has_const_iterator)
{
template<class T>
auto require(const T&) -> valid<
has_type<typename T::const_iterator, is_iterator<_>>
>;
};