接受函数指针的方法上的变分模板
Variadic Templates on Method Accepting Function Pointer
在我看来,下面的代码应该可以正常工作,但它会产生
C2738: could not deduce template argument for 'Type'.
在VS2013中。
template <typename ReturnType, typename...Args>
uint GetParameterSize(ReturnType(*method)(Args...))
{
return ParameterSize<Args...>();
}
template <typename Type, typename...Remaining>
uint ParameterSize()
{
uint output = sizeof(Type);
if (sizeof...(Remaining) > 0)
{
output += ParameterSize<Remaining...>();
}
return output;
}
void MyMethod3(int a, char b, int c )
{
}
// Elsewhere
uint size = GetParameterSize(&MyMethod3);
我想,"哦,也许是因为它没有最终条件。"所以我补充道:
template <typename Type>
uint ParameterSize()
{
return sizeof(Type);
}
导致
C2668: 'ParameterSize' ambiguous call to overloaded function.
我的意思是,它看起来很简单,我认为它应该起作用。编译器怎么能不推导这些参数呢?我是一个新的可变模板,所以我可能会错过一些东西,但一些帮助将不胜感激。谢谢
if (sizeof...(Remaining) > 0)
{
output += ParameterSize<Remaining...>();
}
问题是,上面的代码是运行时检查,而不是编译时。因此,即使一旦Remaining
的长度为0,它仍然必须编译ParamaterSize<>()
的签名,即使它永远不会被执行。
对于这类问题,您实际上可以在编译时执行所有操作。
template<typename ... Args>
struct ParameterSize;
{
static const uint value = 0;
};
template<typename Type, typename... Remain>
struct ParameterSize<Type, Remain...>
{
static const uint value = sizeof(Type) + ParameterSize<Remain...>::value;
};
template <typename ReturnType, typename...Args>
uint GetParameterSize(ReturnType(*method)(Args...))
{
return ParameterSize<Args...>::value;
}
示例位于http://ideone.com/6aYRzI
我能想到的最简单的修复方法是调用过载解析:
template <typename Type>
constexpr unsigned ParameterSize(int)
{
return sizeof(Type);
}
template <typename Type, typename...Remaining>
constexpr unsigned ParameterSize(...)
{
return sizeof(Type) + ParameterSize<Remaining...>(42);
}
template <typename ReturnType, typename...Args>
constexpr unsigned GetParameterSize(ReturnType(*method)(Args...))
{
return ParameterSize<Args...>(42);
}
void MyMethod3(int a, char b, int c )
{
}
int main()
{
// Elsewhere
unsigned size = GetParameterSize(&MyMethod3);
}
对于类型为int
(如42
)的参数,省略号使第二个重载比第一个重载匹配得更差,这就是解决歧义(ParameterSize<one_argument>(42)
)的方法。
对于您的代码不起作用的原因还有其他答案,所以我会给您一个替代方案。由于您似乎在累积sizeof(Type)
以获得存储函数参数所需的总堆栈大小,因此我将如何做到这一点:
#include <iostream>
#include <algorithm>
template <class ... Args>
unsigned ParameterSize()
{
unsigned sizes[sizeof...(Args)] = {sizeof(Args)...};
return std::accumulate(std::begin(sizes), std::end(sizes), 0);
}
template <typename ReturnType, typename...Args>
uint GetParameterSize(ReturnType(*method)(Args...))
{
return ParameterSize<Args...>();
}
void MyMethod(int,int,int){}
int main()
{
std::cout << GetParameterSize(&MyMethod) << std::endl;
}
由于您的示例中已经有了运行时代码,我假设您不介意在运行时完成一些工作。
相关文章:
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 使用std::函数映射对象方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 初始化具有非默认构造函数的std::数组项的更好方法
- 如何制作一个将函数作为参数的类方法
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 获取从C++中同一类中的构造函数调用的方法返回的值
- C++ - 类方法函数指针unordered_map的初始化器列表
- 如何从具有多个对象/字段的类中调用方法函数
- 如何以这种方式访问另一个文件的方法/函数
- Vim 转到标准库方法/函数定义
- 在方法/函数中使用"static const std::string"还是只使用"cons
- 我可以将这两种方法/函数合二为一吗?
- 为什么我不能添加到方法/函数外部的 ostringstream
- 如何在调用方法函数中将列表、向量或数组作为参数传递
- 如何专门化模板化类,以采用不带参数的方法函数类型
- 类方法/函数中的指针
- 修改参数和/或返回新实例的方法/函数的命名约定
- 在Lua中跟踪变量以进行读访问,以启动用户定义的c++方法/函数
- 调试可视化工具在预览中使用成员方法/函数调用