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

Detect the maximum numbers of arguments a function can take using template metaprogramming

本文关键字:函数 数数 参数 一个 可以使 检测 编程      更新时间:2023-10-16

考虑以下代码:

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

我想要一个可以找到可可f可以使用的类型T的最大参数。

例如,对于以下过载集:

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;
}

您问的不是完全微不足道...

如果您对单独单独使用的最大整数数量感兴趣,则可以使用通用标识符调用函数或一组函数,则不包括其他类型的呼叫...

我的意思是...如果检查以下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您获得4,从g获得size_t(-1)g()不确定),从h()中您获得63(最大值减去1)。