1

我正在编写一个物理模拟程序,我想做以下事情:我有一个 hana 适应结构,我想在编译时检查这个结构是否有名为“absorbedEnergy”的成员,使用:

if constexpr ( ... )

在我使用的 c++17 中这样做的正确方法是什么?

现在使用hana文档我想出了这个:

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 的论点 - 细胞不是恒定的表达。有没有解决的办法?

4

1 回答 1

1

您的问题似乎与标准中对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

于 2019-05-07T09:30:56.720 回答