簡體   English   中英

升壓eval_if的延遲評估

[英]lazy evaluation of boost eval_if

我認為我對eval_if的延遲感到誤解。

下面的代碼是根據眾所周知的成員檢測機制進行調整的,在該機制中,我嘗試添加該成員還應該可以轉換為特定類型的功能。

template <typename T, typename P = size_t>
struct has_height
{
  private:
    using Yes = char[2];
    using No = char[1];

    struct Fallback
    {
        P height;
    };
    struct Derived : T, Fallback
    {
    };

    template <class U>
    static No &test(decltype(U::height) *);

    template <typename U>
    static Yes &test(U *);

  public:
    static constexpr bool has_member = sizeof(test<Derived>(nullptr)) == sizeof(Yes);

    using value_type = std::integral_constant<bool, has_member>;

    static constexpr bool value = boost::mpl::eval_if<
        value_type,
        std::is_convertible<decltype(T::height), P>,
        boost::mpl::identity<std::false_type>>::type::value;
};

template <typename T, typename P>
const bool has_height<T, P>::value;

template <typename T, typename P>
const bool has_height<T, P>::has_member;

但是,在執行以下操作時:

struct TypeA
{
     size_t width;
;

struct TypeB
{
    size_t no_width;
};
EXPECT_TRUE((has_width<TypeA, size_t>::value));
EXPECT_TRUE((has_width<TypeB, size_t>::value));

我收到以下錯誤:

/home/auke/git/base/sdk/src/horus/cmp/prop/reflection/has_width.hpp:49: error: ‘width’ is not a member of refl_test_reflection_types_Test::TestBody()::TypeB’
     static constexpr bool value = boost::mpl::eval_if<
                           ^~~~~

我了解編譯器在說什么,但不明白為什么。 我在這里的假設是,由於條件為假(已測試),因此不評估第二個參數(std :: is_convertible)。

對此問題的任何澄清將不勝感激,可能的修復方法也將很好;)

uke

如果您忘記了boost::mpl一秒鍾,然后看一下它的簡化形式:

eval_if<value_type, A, B>::type::value

應當更加清楚的是,對AB都進行了評估,以使其成為必須評估的第二和第三模板參數。 這樣就不會偷懶。

如果要實現“懶惰”行為,則可以使用模板專門化。

template<bool, class T, class P>
struct has_height_helper {
   // `true` case. Evaluate `T::height`
   static constexpr bool value = std::is_convertible<decltype(T::height), P>::value;
}

template<class T, class P>
struct has_height_helper<false, T, P> {
    static constexpr bool value = false;
}

// And now use the helper in the class
static constexpr bool value = has_height_helper<has_member, T, P>::value;

作為模板規范化,基本上取決於所使用的規范化“隱藏”代碼。

另一種選擇是使用if constexpr隱藏代碼的constexpr函數:

template<bool has_member, class T, class P>
constexpr bool has_height_helper() {
    if constexpr (has_member) {
        return std::is_convertible<decltype(T::height), P>::value;
    } else {
        return false;
    }
}

您可以將其引入結構中:

template <typename T, typename P = size_t>
struct has_height
{
  private:
    struct Fallback
    {
        P height;
    };
    struct Derived : T, Fallback
    {
    };

    template <class U>
    constexpr static bool test(decltype(U::height) *) {
        return std::is_convertible<decltype(T::height), P>::value;
    }

    template <typename U>
    constexpr static int test(U *) {
        // Basically return any non-bool false so we can tell the difference
        return 0;
    }

  public:
    static constexpr bool has_member = std::is_same<test<Derived>(nullptr), bool>::value;

    using value_type = std::integral_constant<bool, has_member>;

    static constexpr bool value = test<Derived>(nullptr);
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM