【问题标题】:Selecting a method using different enable_if conditions使用不同的 enable_if 条件选择方法
【发布时间】:2020-08-10 07:03:44
【问题描述】:

我想写一个通用的验证函数。所以我尝试编写一个元程序。 但它没有被编译,这是正确的。谁能告诉我实现它的方法。

我正在发布我的示例代码。可以有 3 种或更多类型的结构(此处为 A、B、C),一些具有特定类型的标头,另一种具有其他类型的标头,有些甚至没有标头。所以我想编写一个程序来正确选择所需的函数(这里是 f1()、f2() 来验证结构头。我不想使用 Boost Hana 或任何其他反射库。

#include <iostream>

using namespace std;

struct Header
{
    int i;
};

struct OrderHeader
{
    int i; int j;
};

struct A
{
    Header header;
    int val;
};

struct B
{
    OrderHeader order_header;
    int val;
    int c;
};

struct C
{
    int val;
    int c;
};

bool f1(Header h)
{
    return h.i == 1 ? true : false;
}

bool f2(OrderHeader oh)
{
    return (oh.i == 1 and oh.j == 1) ? true : false;
}

template<typename St, typename = enable_if_t<is_same_v<decltype(St::header), Header>>>
using v1 = bool;

template<typename St, typename = enable_if_t<is_same_v<decltype(St::order_header), OrderHeader>>>
using v2 = bool;

template<typename St>
bool validate(St s)
{    
    if constexpr(is_same_v<v1<St>, bool>)
    {
        return f1(s.header);
    }
    else if constexpr(is_same_v<v2<St>, bool>)
    {
        return f2(s.order_header);
    }
    
    return true;
}

int main(int argc, char** argv) 
{         
    A at{1,1};
    A af{};
    C c{};    
    B b{};
    
    cout << boolalpha << validate(at) << endl;
    cout << boolalpha << validate(af) << endl;
    cout << boolalpha << validate(b) << endl;
    cout << boolalpha << validate(c) << endl;
    
    return 0;
} 

【问题讨论】:

    标签: c++ templates c++17 c++20


    【解决方案1】:

    if constexpr 可以作为部分编译的手段,但if 中的条件必须始终是可编译的。在您的情况下,v1&lt;St&gt;v2&lt;St&gt; 仅在 St 的类型正确时才存在,因此会出现错误。

    您可以改用变量模板的特化,例如像这样

    template<typename, typename = void>
    constexpr bool is_v1 = false;
    
    template<typename St>
    constexpr bool is_v1<St, enable_if_t<is_same_v<decltype(St::header), Header>>> = true;
    
    template<typename, typename = void>
    constexpr bool is_v2 = false;
    
    template<typename St>
    constexpr bool is_v2<St, enable_if_t<is_same_v<decltype(St::order_header), OrderHeader>>> = true;
    
    template<typename St>
    bool validate(St s)
    {
        if constexpr (is_v1<St>)
        {
            return f1(s.header);
        }
        else if constexpr (is_v2<St>)
        {
            return f2(s.order_header);
        }
    
        return true;
    }
    

    现在is_v1&lt;St&gt;is_v2&lt;St&gt; 总是返回一些值(truefalse),并且代码应该可以编译1


    1f2() 中还有一个错字:oh.i == 1 and oh.j == 1 应该是oh.i == 1 &amp;&amp; oh.j == 1

    还要注意h.i == 1 ? true : false 是同义词,h.i == 1 就足够了。

    【讨论】:

    • 谢谢老哥的回答。它解决了我的问题。我有错误的印象,如果一个条件不能被评估 constexpr if 离开那个。 'and' 也不是 && 的同义词。接受第二点,只是忽略了:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    • 2022-01-04
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    相关资源
    最近更新 更多