考虑以下示例:
#include <utility>
#include <iostream>
struct bar
{
void baz() { std::cout << "bar::baz" << std::endl; }
};
template <typename Signature>
struct function_traits;
template <typename ReturnType, typename Class, typename ...ArgumentTypes>
struct function_traits<ReturnType (Class::*)(ArgumentTypes...)>
{
typedef ReturnType (Class::*Signature)(ArgumentTypes...);
typedef ReturnType (*FuncPtr)(void const *ip, ArgumentTypes&& ...);
template <Signature mf>
static ReturnType wrapper(void const *p, ArgumentTypes&& ...args)
{
Class* instance = const_cast<Class*>(static_cast<Class const *>(p));
return (instance->*mf)(std::forward<ArgumentTypes>(args)...);
}
};
template <typename Type>
constexpr auto wrap(Type p) -> typename function_traits<Type>::FuncPtr
{
return &(function_traits<Type>::template wrapper<p>); // ERROR: Address of overloaded function 'wrapper' does not match required type 'void (const void *)'
}
int main()
{
auto v = wrap(&bar::baz);
}
我用Xcode 4.5.2测试了它 - Apple clang 4.1版(标签/ Apple / clang-421.11.66)(基于LLVM 3.1svn)
我想要太多吗?
答案 0 :(得分:4)
参数声明
constexpr auto wrap(Type p)
与模板名称
不兼容template wrapper<p>
即使在constexpr
函数中,参数也不能用作常量表达式。
通常这个错误表现为尝试根据参数的值调整constexpr
函数的返回类型,但这是一个小的微妙,因为类型表达式是值计算的一部分,值始终具有相同的类型。
根本问题是要求模板执行运行时工作。您可以决定在运行时调用它的PTMF。
constexpr
永远不会限制可能传递给函数的参数。 (即,只能使用常量参数调用函数。)它仅使函数成为在需要常量的上下文中使用的函数。