为什么涉及std :: enable_if的模板元函数会产生不希望的结果?

Luk*_*keG 4 c++ templates

我有一个类型特征

template <typename T, typename Enable = void>
struct is_binary_function : std::false_type {};
Run Code Online (Sandbox Code Playgroud)

及其专业化

template <typename function_t>
struct is_binary_function<function_t,
                          std::enable_if_t<
                              !std::is_void_v<typename function_t::result_t> &&
                              !std::is_void_v<typename function_t::parameter1_t> &&
                              !std::is_void_v<typename function_t::parameter2_t> &&
                              function_t::isBinaryCallable
                              , function_t>
        > : std::true_type {};
Run Code Online (Sandbox Code Playgroud)

我试图找出类,具有公共类型定义result_t,parameter1_t以及parameter2_t,以及静态常量isBinaryCallabletrue值.

但是,以下代码不会输出我期望的内容:

struct f {
    using result_t = float;

    using parameter1_t = float;
    using parameter2_t = float;

    static constexpr bool isBinaryCallable = true;
};


int main() {
    using function_t = f;

    std::cout << is_binary_function<f>::value << '\n'; //Error: outputs false, instead of true
    std::cout << std::is_void_v<function_t::result_t> << '\n'; //false, as expected
    std::cout << std::is_void_v<function_t::parameter1_t> << '\n'; //false, as expected
    std::cout << std::is_void_v<function_t::parameter2_t> << '\n'; //false, as expected
    std::cout << function_t::isBinaryCallable << '\n'; //true, as expected
    std::cout << (!std::is_void_v<typename function_t::result_t> &&
        !std::is_void_v<typename function_t::parameter1_t> &&
        !std::is_void_v<typename function_t::parameter2_t> &&
        function_t::isBinaryCallable) << '\n'; // true, as expected.
}
Run Code Online (Sandbox Code Playgroud)

我想我对元函数模式的使用存在缺陷,但我无法弄清楚我做错了什么.

为什么上述元函数不能按预期工作?

我使用的是Visual Studio 2017,设置为C++ 17 Standard.

Yak*_*ont 8

std::enable_if_t<
                          !std::is_void_v<typename function_t::result_t> &&
                          !std::is_void_v<typename function_t::parameter1_t> &&
                          !std::is_void_v<typename function_t::parameter2_t> &&
                          function_t::isBinaryCallable
                          , function_t>
Run Code Online (Sandbox Code Playgroud)

应该

std::enable_if_t<
                          !std::is_void_v<typename function_t::result_t> &&
                          !std::is_void_v<typename function_t::parameter1_t> &&
                          !std::is_void_v<typename function_t::parameter2_t> &&
                          function_t::isBinaryCallable
                          , void>
Run Code Online (Sandbox Code Playgroud)

要么

std::enable_if_t<
                          !std::is_void_v<typename function_t::result_t> &&
                          !std::is_void_v<typename function_t::parameter1_t> &&
                          !std::is_void_v<typename function_t::parameter2_t> &&
                          function_t::isBinaryCallable>
Run Code Online (Sandbox Code Playgroud)

因为is_binary_function<f>::valueis_binary_function<f, void>::value如在主模板特指定is_binary_function(第二参数默认为void),同时

std::enable_if_t<
                          !std::is_void_v<typename function_t::result_t> &&
                          !std::is_void_v<typename function_t::parameter1_t> &&
                          !std::is_void_v<typename function_t::parameter2_t> &&
                          function_t::isBinaryCallable
                          , function_t>
Run Code Online (Sandbox Code Playgroud)

过去了function_tff,没有void.所以它无法匹配.