2012-05-11 4 views
0

Пусть мы имеем:Определение количества аргументов C++ шаблона функтора

template<typename F, typename T1, typename T2> 
void my_magic_method(F func, T1 t1, T2 t2) 
{ 
    if (???) 
     func(t1); 
    else 
     func(t1,t2); 
} 

Что может помочь мне определить:

  1. Количество аргументов

  2. Может быть, типы каждого аргумента

  3. Тип возвращаемого значения

Я не могу использовать VARIADIC шаблоны из-за МСВС 2010 ...

UPDATE

Мой первый раствор:

template<typename F> 
auto my_magic_func(F f) -> decltype(f(1)) 
{ 
    return f(1); 
} 

template<typename F> 
auto my_magic_func(F f, void * fake = NULL) -> decltype(f(2,3)) 
{ 
    return f(2,3); 
} 

int main() 
{ 
    auto x1 = my_magic_func([](int a){ return a+100; }); 
    auto x2 = my_magic_func([](int a, int b){ return a*b; }); 
    // x1 == 1+100 
    // x2 == 2*3 
} 

Вот мой образ функции типа перегрузки. Это работает, но, может быть, лучше солить?

ответ

3

Не совсем то, что вы просили, но если я понимаю ваше намерение правильно, в VC++ 2010, это возможно (но некрасиво) с помощью простой перегрузки на основе арности:

#include <utility> 
#include <string> 
#include <iostream> 

template<typename F, typename T1> 
auto my_magic_method(F&& func, T1&& t1) -> 
    decltype(std::forward<F>(func)(std::forward<T1>(t1))) 
{ 
    return std::forward<F>(func)(std::forward<T1>(t1)); 
} 

template<typename F, typename T1, typename T2> 
auto my_magic_method(F&& func, T1&& t1, T2&& t2) -> 
    decltype(std::forward<F>(func)(std::forward<T1>(t1), std::forward<T2>(t2))) 
{ 
    return std::forward<F>(func)(std::forward<T1>(t1), std::forward<T2>(t2)); 
} 

struct string_to_float_functor 
{ 
    float operator()(std::string const& s) const 
    { 
     return std::stof(s); 
    } 
}; 

int main() 
{ 
    auto a = my_magic_method([](std::string const& x) { return x + x; }, "foo"); 
    auto b = my_magic_method([](double x, int y) { return x * y; }, 21.5, 3); 
    auto c = my_magic_method(string_to_float_functor(), "3.14159265"); 
    std::cout << a << '\n' << b << '\n' << c << '\n'; 
} 

Это поддерживает унарные и бинарные функторы – продолжают шаблон и добавление перегрузок для других объектов по мере необходимости.

+0

Моя проблема заключается в определении числа аргументов typename F. В вашем решении есть 2 разных my_magic_funcs для определения. Моя текущая проблема слишком сложна по сравнению с моим вопросом. Это только часть его. – k06a

+1

@ k06a: Ваша проблема - проблема [XY] (http://meta.stackexchange.com/a/66378/166663) - если вы сказали, что пытаетесь выполнить, а не как пытаетесь (и неудача), чтобы выполнить его, было бы намного легче помочь вам. – ildjarn

+1

@ k06a: так почему вы ** задали ** этот вопрос, если вы не ответили на вопрос? Почему бы вам не спросить о проблеме, которую вы действительно хотите решить, а не о другой, более простой, решение которой вы ** не заботитесь? – jalf

0

Вот несколько подходов; все предполагают C++ 11. Протестировано на clang ++ 3.2 с -std = C++ 11.

//Taking a function pointer argument (template types inferred) 

template <typename ret, typename ... Args> 
constexpr int arg_count(ret (*f)(Args...)) { 
    return sizeof...(Args); 
} 

//Taking a function type (or related) directly 

template <typename T> 
struct ArgCount { 
    static const int value = 0; 
}; 

template <typename Ret, typename ... Args> 
struct ArgCount<Ret(Args...)> { 
    static const int value = sizeof...(Args); 
}; 

template <typename Ret, typename ... Args> 
struct ArgCount<Ret(*)(Args...)> { 
    static const int value = sizeof...(Args); 
}; 

template <typename Ret, typename ... Args> 
struct ArgCount<Ret(&)(Args...)> { 
    static const int value = sizeof...(Args); 
}; 

//Using the latter for dispatch 

template <int N> 
struct helper { 
    template<typename F, typename T1, typename T2> 
    static void call(F func, T1 t1, T2 t2); 
}; 

template <> 
struct helper<1> { 
    template<typename F, typename T1, typename T2> 
    static void call(F func, T1 t1, T2 t2) { 
     func(t1); 
    } 
}; 

template <> 
struct helper<2> { 
    template<typename F, typename T1, typename T2> 
    static void call(F func, T1 t1, T2 t2) { 
     func(t1, t2); 
    } 
}; 

template<typename F, typename T1, typename T2> 
void my_magic_method(F func, T1 t1, T2 t2) 
{ 
    helper<ArgCount<F>::value>::call(func, t1, t2); 
} 

//Testing 

#include <cstdio> 

void a(int a, int b) { printf("%i\n", a + b); } 
void b(int x) { printf("%i\n", x); } 

int main() { 
    printf("%i %i\n", arg_count(a), arg_count(b)); 
    printf("%i %i\n", ArgCount<decltype(a)>::value, ArgCount<decltype(b)>::value); 
    my_magic_method(a, 1, 2); 
    my_magic_method(b, 1, 2); 
} 
+0

Я думаю, вы должны объяснить больше, почему это делается, чтобы OP полностью понимал ваши подходы. – ForceMagic

Смежные вопросы