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

时间:2018-08-20 18:21:34

标签: c++ templates

我有类型特征

template <typename T, typename Enable = void>
struct is_binary_function : std::false_type {};

及其专业化

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 {};

我正在尝试标识具有公共类型定义result_tparameter1_tparameter2_t的类,以及具有值true的静态常量isBinaryCallable

但是,以下代码无法输出我期望的结果:

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.
}

我猜我对元功能模式的使用存在缺陷,但是我无法弄清楚自己做错了什么。

为什么上述元功能无法按预期工作?

我正在使用Visual Studio 2017,设置为C ++ 17 Standard。

1 个答案:

答案 0 :(得分: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>

应该是

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>

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>

同时,由于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>

function_t的形式f通过f而不是void时。因此无法匹配。