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でテストしました-Appleclangバージョン4.1(tags / Apple / clang-421.11.66)(LLVM 3.1svnに基づく)
私はあまりにも欲しいですか?

4

1 に答える 1

4

パラメータ宣言

constexpr auto wrap(Type p)

template-nameと互換性がありません

template wrapper<p>

関数であってもconstexpr、パラメータを定数式として使用することはできません。

constexpr通常、このエラーは、引数の値に従って関数の戻り型を調整しようとする試みとして現れますが、型式は値の計算の一部であり、値は常に同じ型であるため、これは少し微妙です。

基本的な問題は、テンプレートが実行時の作業を行うように求められていることです。実行時にどのPTMFで呼び出すかを決定できます。

constexpr関数に渡される可能性のある引数を制限することはありません。(つまり、関数は定数引数を使用してのみ呼び出すことができます。)これにより、関数は定数が必要なコンテキストで使用するための候補になります。

于 2013-01-23T08:36:20.610 に答える