Как правильно проверить член во время компиляции с boost :: hana? - PullRequest
1 голос
/ 07 мая 2019

Я пишу программу симуляции физики и хочу сделать следующее: у меня есть адаптированная структура hana, и я хочу проверить, есть ли у этой структуры член с именем "bedbedEnergy "во время компиляции, используя:

if constexpr ( ... )

Каков правильный способ сделать это в c ++ 17, который я использую?

Теперь, используя документацию по хане, я придумал это:

struct HasAE { double absorbedEnergy };
struct HasNoAE {};

temaplate<typename Cell>
void irelevantFunction(Cell& cell){
    auto has_absorbedEnergy = hana::is_valid(
        [](auto &&p) -> decltype((void) p.absorbedEnergy) {});

    if constexpr(has_absorbedEnergy(cell)) { ... }
}

HasAE cell;
HasNoAE anotherCell;
cell.absorbedEnergy = 42; //value known at runtime

irelevantFunction(cell);
irelevantFunction(anotherCell);

Дело в том, что этопрекрасно компилируется с g ++ 7.4.0 и делает то, что я ожидаю, но не компилируется с clang ++ - 8.Выдает ошибку:

constexpr, если условие не является константным выражением

Я подозреваю, что это происходит из-за того, что аргумент has_absorbedEnergy - ячейка не является и константным выражением,Есть ли способ обойти это?

1 Ответ

1 голос
/ 07 мая 2019

Ваша проблема, похоже, связана с требованием в стандарте для выражения в if constexpr быть "контекстно-преобразованным константным выражением типа bool" (см. этот вопрос ).Вы можете обойти это, изменив if constexpr на:

if constexpr (decltype(has_absorbedEnergy(cell)){})

https://wandbox.org/permlink/hmMNLberLJmt0ueJ


В качестве альтернативы, вы можете использовать выражение SFINAE для достижения того, чего вы хотите (см. cppreference.com документация std::void_t):

#include <type_traits>
#include <iostream>

template <typename, typename= std::void_t<>>
struct has_absorbedEnergy : std::false_type {};

template <typename T>
struct has_absorbedEnergy<T,
  std::void_t<decltype(std::declval<T&>().absorbedEnergy)>>
    : std::true_type {};

template <typename Cell>
void irelevantFunction([[maybe_unused]] Cell &cell) {
  if constexpr (has_absorbedEnergy<Cell>::value)
    std::cout << "Has absorbedEnergy\n";
  else
    std::cout << "Does not have absorbedEnergy\n";
}

struct HasAbsorbedEnergy
  { int absorbedEnergy; };

struct DoesNotHaveAbsorbedEnergy
  {};

int main()
{
HasAbsorbedEnergy Has;
DoesNotHaveAbsorbedEnergy DoesNot;

irelevantFunction(Has);
irelevantFunction(DoesNot);
}

https://wandbox.org/permlink/0559JhpVQBOwHC0Z

...