2

関数を型にバインドしようとしています-次のテストプログラムを検討してください:

#include <utility>

template <class Ret, class Arg>
struct func {
    typedef Ret (&ref)(Arg);
    template <ref Fn>
    struct bind {
        template <class NewArg>
        Ret operator()(NewArg&& arg) {
            return Fn(std::forward<Arg>(arg));
        }
    };
};

int foo(int i) {
    return i;
}

typedef func<int, int>::bind<foo> Foo;

int main(int argc, char** argv) {
    Foo foo_obj;
    return foo_obj(argc);
}

これは機能しますが、私は個人的にfunc<int, int>::bind<foo>醜く、冗長でもあります-しかし、私はそうすることができないようで、func::bind<foo>RetとArgをテンプレート引数から推論してバインドします(または道徳的に同等のもの)。私はこのようなことをします:

template <class Ret, class Arg>
constexpr auto bind_func(typename func<Ret, Arg>::ref f) -> typename func<Ret, Arg>::bind<f> {
    return {};
}

ただし、fが定数式であることが保証されていないため、コンパイラはfが有効なテンプレート引数であることを認識できないため、コンパイルできません。

一定の冗長性なしでこれを達成する方法はありますか?

4

1 に答える 1

1

マクロが受け入れられる場合、考えられる解決策は次のとおりです。

#include <utility>

template <class Ret, class Arg>
struct func {
    typedef Ret (&ref)(Arg);
    template <ref Fn>
    struct bind {
        template <class NewArg>
        Ret operator()(NewArg&& arg) {
            return Fn(std::forward<Arg>(arg));
        }
    };
};

template<typename T>
struct traits { };

template<typename R, typename A>
struct traits<R(A)>
{
    typedef R return_type;
    typedef A arg_type;
};

int foo(int i) {
    return i;
}

#define TYPE_WRAP(f) \
    func< \
        traits<decltype(f)>::return_type, \
        traits<decltype(f)>::arg_type \
        >::bind<f>

int main(int argc, char** argv) {
    TYPE_WRAP(foo) foo_obj;
    return foo_obj(argc);
}
于 2013-02-25T01:00:11.040 に答える