使用模板元编程检测函数可以采用的最大参数数

时间:2017-12-17 14:54:06

标签: c++ function parameters c++17 template-meta-programming

请考虑以下代码:

template <class T, class F>
std::size_t maximum_number_of_arguments(F&& f) {
    // Code here
}

我想要一个能够找到可调用T可以采用的类型f的最大参数数量的函数。

例如,对于以下过载集:

void f(int, int); // f called with 2 ints compiles
void f(int, int, int); // f called with 3 ints compiles
void f(int, char, int, double); // f called with 4 ints compiles
void f(int, std::string, int, int, int); // f called with 5 ints does not compile

结果:

maximum_number_of_arguments<int>(f)

应该返回4

我想要修复一个函数可以采用的限制数量参数的方法(例如256),并测试所有可能性,并跟踪无法编译的调用。如何使用template / contexpr元编程实现这一点?

编辑:回答关于我们无法将重载集传递给函数的事实的评论(我的f示例可能不是最好的):

#include <iostream>

struct functor
{
    void operator()(int) {std::cout << "int" << std::endl;}
    void operator()(int, int) {std::cout << "int, int" << std::endl;}
    void operator()(int, int, int) {std::cout << "int, int, int" << std::endl;}
};

template <class F>
void caller(F&& f)
{
    std::forward<F>(f)(1);
    std::forward<F>(f)(1, 2);
    std::forward<F>(f)(1, 2, 3);
}

int main(int argc, char* argv[])
{
    functor f;
    caller(f);
    return 0;
}

1 个答案:

答案 0 :(得分:3)

你问的不是微不足道的......

如果您对单独可用于调用函数或具有公共标识符的函数集的最大整数数感兴趣,则排除其他类型的调用...

我的意思是......如果检查以下一组f()函数

void f(int, int); 
void f(int, char, int);
void f(int, std::string, int, int, int); // excluded by std::string

应该获得3,因为要排除收到std::string的版本...

嗯......用宏(因此我的解决方案是内在的邪恶)定义了一个专用于符号的检查结构

setMaxStruct(f);

您可以获得最大数量的整数参数(具有可设置但默认的最大值),编写如下内容

std::cout << "--- f: " << getMaxArgsFor_f<int>::value << std::endl;

以下是一个完整的工作示例

#include <utility>
#include <iostream>
#include <type_traits>

template <typename T, std::size_t>
using typer = T;

#define setMaxStruct(func)                                        \
                                                                  \
template <typename Type, std::size_t MaxArgs = 64U>               \
struct getMaxArgsFor_ ## func                                     \
 {                                                                \
   template <typename, std::size_t ...>                           \
   static std::false_type isCallable (...);                       \
                                                                  \
   template <typename T, std::size_t ... Is>                      \
   static auto isCallable (int)                                   \
      -> decltype( func(std::declval<typer<T, Is>>()...),         \
                   std::true_type{} );                            \
                                                                  \
   template <typename T, std::size_t ... Is>                      \
   static constexpr bool getMaxTH3                                \
      (std::index_sequence<Is...> const &)                        \
    { return decltype(isCallable<T, Is...>(0))::value; }          \
                                                                  \
   template <typename T, std::size_t I>                           \
   static constexpr bool getMaxTH2 ()                             \
    { return getMaxTH3<T>(std::make_index_sequence<I>{}); }       \
                                                                  \
   template <typename T, std::size_t ... Is>                      \
   static constexpr std::size_t getMaxTH1                         \
      (std::index_sequence<Is...> const &)                        \
    {                                                             \
      std::size_t ret ( -1 );                                     \
                                                                  \
      ( (ret = getMaxTH2<T, Is>() ? Is : ret), ...);              \
                                                                  \
      return ret;                                                 \
    }                                                             \
                                                                  \
   template <typename T, std::size_t MaxAs>                       \
   static constexpr std::size_t getMaxT ()                        \
    { return getMaxTH1<T>(std::make_index_sequence<MaxAs>{}); }   \
                                                                  \
   static constexpr std::size_t value = getMaxT<Type, MaxArgs>(); \
 }

void f(int, int);
void f(int, int, int);
void f(int, char, int, double);
void f(int, std::string, int, int, int);

template <typename ... Args>
void h (Args ... args);

setMaxStruct(f);
setMaxStruct(g);
setMaxStruct(h);

int main()
 {
   std::cout << "--- f: " << getMaxArgsFor_f<int>::value << std::endl;
   std::cout << "--- g: " << getMaxArgsFor_g<int>::value << std::endl;
   std::cout << "--- h: " << getMaxArgsFor_h<int>::value << std::endl;
 }

f得到4g得到size_t(-1) g()h()未定义),63得到1 function translate($google) { $en = array( "Mother", "Father" ); $de= array( "Mutter", "Vater" ); $s = str_replace($en,$de,$google); return $s;} (最大值减去$en = array( "Mother", "Father" ); $de= array( "Mutter", "Vater" ); function translate($google, $en, $de) { $s = str_replace($en,$de,$google); return $s; } )。