2

_CallWithRightmostArgsInnerSFINAEが適切に機能するように関数を適切に失敗させるため に考えられることは何でもしようとしましたが、この試みでVS2013は私にエラーを与えました:error C2039: 'type' : is not a member of 'std::enable_if<false,void>'

何か案は?より良い代替手段はありますか?ここでの考え方は、Function が NumArgs で示される数値またはパラメーターを受け取るという条件で、Function への関数呼び出しを行いたいということです。最後の 2 つの可変引数は関数に転送され、結果が返されます。

template <typename Function, int NumArgs>
class SplitParameters {
public:
    typedef typename function_traits<Function>::result_type result_type;

    template <typename ... RightArgs>
    static result_type CallWithRightmostArgs(const Function& call, RightArgs && ... rightArgs) {
        static_assert(sizeof...(RightArgs) >= NumArgs, "Unable to make function call with fewer than minimum arguments.");
        return _CallWithRightmostArgs(call, std::forward<RightArgs>(rightArgs)...);
    }

private:
    template <typename ... RightArgs>
    static result_type _CallWithRightmostArgs(const Function& call, RightArgs && ... rightArgs) {
        return _CallWithRightmostArgsInner(call, std::forward<RightArgs>(rightArgs)...);
    }

    // note the '==' vs '!=' in these two functions.  I would assume that only one could exist
    template <typename LeftArg, typename ... RightArgs, typename std::enable_if<sizeof...(RightArgs) != NumArgs>::type* = 0>
    static result_type _CallWithRightmostArgsInner(const Function& call, LeftArg, RightArgs && ... rightArgs) {
        return _CallWithRightmostArgs(call, std::forward<RightArgs>(rightArgs)...);
    }

    template <typename LeftArg, typename ... RightArgs, typename std::enable_if<sizeof...(RightArgs) == NumArgs>::type* = 0>
    static result_type _CallWithRightmostArgsInner(const Function& call, LeftArg, RightArgs && ... rightArgs) {
        return call(std::forward<RightArgs>(rightArgs)...);
    }
};
4

1 に答える 1

3

あなたのコードを

    #include <iostream>

    template <class T>
    struct function_traits
    {
        typedef void result_type;
    };

    template <typename Function, int NumArgs>
    class SplitParameters {
    public:
        typedef typename function_traits<Function>::result_type result_type;

        template <typename ... RightArgs>
        static result_type CallWithRightmostArgs(const Function& call, RightArgs && ... rightArgs) {
            static_assert(sizeof...(RightArgs) >= NumArgs, 
                          "Unable to make function call with fewer than minimum arguments.");
            return _CallWithRightmostArgs(call, std::forward<RightArgs>(rightArgs)...);
        }

    private:
        template <typename ... RightArgs>
        static result_type _CallWithRightmostArgs(const Function& call, RightArgs && ... rightArgs) {
            return _CallWithRightmostArgsInner(call, std::forward<RightArgs>(rightArgs)...);
        }

        // note the '==' vs '!=' in these two functions.  I would assume that only one could exist
        template <typename LeftArg, typename ... RightArgs, class = typename std::enable_if<sizeof...(RightArgs) != NumArgs -1 >::type>
        static result_type _CallWithRightmostArgsInner(const Function& call, LeftArg, RightArgs && ... rightArgs) {
            return _CallWithRightmostArgsInner(call, std::forward<RightArgs>(rightArgs)...);
        }

        template <typename ... RightArgs, class = typename std::enable_if<sizeof...(RightArgs) == NumArgs>::type>
        static result_type _CallWithRightmostArgsInner(const Function& call, RightArgs && ... rightArgs) {
            return call(std::forward<RightArgs>(rightArgs)...);
        }
    };

    void f(int i, int j)
    {
        std::cout << i << ' ' << j << std::endl;
    }

    int main()
    {
        SplitParameters<decltype(f), 2>::CallWithRightmostArgs(f, 1, 2, 3, 4);
    }

_CallWithRightmostArgsコンパイラはからの呼び出しを好まなかったので、実際に関数_CallWithRightmostArgsInnerを呼び出そうとしていると思いました。g++ もテンプレート パラメーター リストでの変換を 好まなかったので、代わりにそれを変更しました。Inner
0void*class = enable_if<...>::type

失敗した理由を詳しく調べていませんが、うまくいけばこれで十分です。

編集:拒否されたことに関してtypename enable_if<...>::type* = 0、私は同様の問題があることを思い出しましたstd::array

    template <class T, int size>
    void f(const std::array<T,size>&){}

この小さなスニペットは、それ自体で問題なくコンパイルされますが、コンパイルすると次のようになります。

    std::array<int,4> a;
    f(a);

    g++ gives:
    test3.cpp: In function ‘int main()’:
    test3.cpp:9:8: error: no matching function for call to ‘f(std::array<int, 4ul>&)’
         f(a);
            ^
    test3.cpp:9:8: note: candidate is:
    test3.cpp:4:6: note: template<class T, int size> void f(const std::array<T, size>&)
     void f(const std::array<T,size>&){}
          ^
    test3.cpp:4:6: note:   template argument deduction/substitution failed:
    test3.cpp:9:8: note:   mismatched types ‘int’ and ‘#‘integer_cst’ not supported by dump_type#<type error>’
         f(a);
            ^
    test3.cpp:9:8: note:   ‘std::array<int, 4ul>’ is not derived from ‘const std::array<T, size>’

int結局のところ、問題は、sizeパラメーターとして を受け取るようにテンプレートを宣言したことですが、コンパイラーが取得したのstd::size_tは と同じではない でありint、たとえそれらの間で簡単に変換できるとしてもです。上記の例では、これは単なるリテラルであるため、
置き換えることさえできません。コンパイラーにそれを受け入れさせる必要があります (のデフォルトの型は であるため)。 = 0= NULL0L= (void*)0enable_if<true>::typevoid

于 2013-09-11T17:45:50.400 に答える