我有一段非常复杂的代码,我将其简化为这个复制器:

#include <type_traits>
#include <tuple>
template<typename ...As>
struct outer {
    template<typename ...Bs>
    struct inner {
        template<bool dummy, typename E = void>
        struct problem;
        using TA = std::tuple<As...>;
        using TB = std::tuple<Bs...>;

        template<bool dummy>
        struct problem<dummy, typename std::enable_if<std::tuple_size<TA>::value < std::tuple_size<TB>::value>::type>
        {
            static constexpr auto val() { return 1; } // actually a complex function
        };

        template<bool dummy>
        struct problem<dummy, typename std::enable_if<std::tuple_size<TA>::value >= std::tuple_size<TB>::value>::type>
        {
            static constexpr auto val() { return 0; }
        };
    };
};

int main() {
    return outer<int, float>::inner<double>::problem<false>::val();
}

它不编译(使用 gcc 或 clang),说:
<source>:13:82: error: failed requirement 'std::tuple_size<std::tuple<int, float> >::value < std::tuple_size<std::tuple<double> >::value'; 'enable_if' cannot be used to disable this declaration

        struct problem<dummy, typename std::enable_if<std::tuple_size<TA>::value <std::tuple_size<TB>::value>::type>

                                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~

<source>:27:31: note: in instantiation of template class 'outer<int, float>::inner<double>' requested here

    return outer<int, float>::inner<double>::problem<false>::val();

我尝试了一些变体,但没有任何效果。

我阅读了一些已经发布的问答,例如:
this one
this one
但他们似乎没有回答我的问题。

PS:我可以使用 C++17,但这必须适用于任何编译器。

最佳答案

建议:尝试如下

struct inner {
    using TA = std::tuple<As...>;
    using TB = std::tuple<Bs...>;

    template<bool dummy, typename UA = TA, typename E = void>
    struct problem;

    template<bool dummy, typename UA>
    struct problem<dummy, UA,
       std::enable_if_t<(std::tuple_size_v<UA> < std::tuple_size_v<TB>)>>
     { static constexpr auto val() { return 1; } };

    template<bool dummy, typename UA>
    struct problem<dummy, UA,
       std::enable_if_t<(std::tuple_size_v<UA> >= std::tuple_size_v<TB>)>>
     { static constexpr auto val() { return 0; } };
};

我的意思是......考虑到 SFINAE 对您想要启用/禁用的结构/类(或函数或方法)的模板参数进行测试。

原始代码中的问题是 SFINAE 测试仅考虑 TATB ,它们是在包含 innerproblem 结构中定义的类型。因此,测试仅取决于外部模板参数( As...Bs... ),而不取决于 problem 的模板参数。

problem 添加具有默认值的模板参数
// ..................VVVVVVVVVVVVVVVVV
template<bool dummy, typename UA = TA, typename E = void>
struct problem;

不会改变 problem 本身的实际使用,而是转换 std::enable_if 中的测试
template<bool dummy, typename UA>
struct problem<dummy, UA, // ..........VV  UA, not TA
   std::enable_if_t<(std::tuple_size_v<UA> < std::tuple_size_v<TB>)>>
 { static constexpr auto val() { return 1; } };

在涉及 problem 本身的模板参数的测试中。

关于c++ - std::enable_if 不能用于禁用此声明,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56444569/

10-11 00:39