3

考虑以下示例:

#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 (tags/Apple/clang-421.11.66) (基于 LLVM 3.1svn) 对其进行了测试
我想要太多吗?

4

1 回答 1

4

参数声明

constexpr auto wrap(Type p)

与模板名称不兼容

template wrapper<p>

即使在constexpr函数中,参数也不能用作常量表达式。

通常这个错误表现为试图constexpr根据参数的值调整函数的返回类型,但这有点微妙,因为类型表达式是值计算的一部分,值总是具有相同的类型。

根本问题是模板被要求执行运行时工作。您可以决定在运行时使用什么 PTMF 来调用它。

constexpr从不限制可以传递给函数的参数。(即,只能使用常量参数调用函数。)它只会使函数成为在需要常量的上下文中使用的候选者。

于 2013-01-23T08:36:20.610 回答