如何在编译时使用 boost::hana 正确检查成员?
How to properly check for member at compile time with boost::hana?
我正在编写物理模拟程序,我想执行以下操作:
我有一个 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 if 条件不是常量表达式
我怀疑这是因为 has_absorbedEnergy - cell 的参数不是常量表达式。有解决办法吗?
您的问题似乎与 if constexpr
中的表达式为 "contextually converted constant expression of type bool
" 的标准要求有关(参见 )。您可以通过将 if constexpr
更改为:
来解决此问题
if constexpr (decltype(has_absorbedEnergy(cell)){})
https://wandbox.org/permlink/hmMNLberLJmt0ueJ
或者,您可以使用表达式 SFINAE 来实现您想要的(请参阅 std::void_t
的 cppreference.com 文档):
#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);
}
我正在编写物理模拟程序,我想执行以下操作: 我有一个 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 if 条件不是常量表达式
我怀疑这是因为 has_absorbedEnergy - cell 的参数不是常量表达式。有解决办法吗?
您的问题似乎与 if constexpr
中的表达式为 "contextually converted constant expression of type bool
" 的标准要求有关(参见 if constexpr
更改为:
if constexpr (decltype(has_absorbedEnergy(cell)){})
https://wandbox.org/permlink/hmMNLberLJmt0ueJ
或者,您可以使用表达式 SFINAE 来实现您想要的(请参阅 std::void_t
的 cppreference.com 文档):
#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);
}