A quick note: you can use C++11 templates to detect struct fields by name and type, and statically branch on them. I first heard of this solution from breeze1990.
Say I want to detect if a struct has a field size
of type int
.
Create two template instantiations of the same name,
here HasStaticSize
that defaults to false.
#include <type_traits>
template <typename T, typename = void>
struct HasStaticSize : std::false_type {};
template <typename T>
struct HasStaticSize<
T, typename std::enable_if<
std::is_same<int, std::decay_t<decltype(T::size)>>::value,
void>::type> : std::true_type {};
The latter is only resolved if T::size
is declared as int
,
or more specifically, something that “decays” to int
.
The outcome of these two is inheriting from structs
whose ::value
member is constant true
or false
.
Then you can use constexpr
in an if
to branch on the check
(::value
extracts a boolean member from the templated struct),
and behave differently based on the result.
struct Foo {
static constexpr int size = 7;
};
int wat() {
if constexpr (HasStaticSize<Foo>::value) {
return 0;
}
return 1;
}
Godbolt link, which shows the compiled code only has one branch, either returning 0 or 1 based on whether the field name resolves and the type matches.
Note removing the decay_t
will change the result,
because apparently decay
removes const
.
You could also remove it and compare to const int
.
This is all weird and I don’t really like C++ template metaprogramming.
Want to respond? Send me an email, post a webmention, or find me elsewhere on the internet.
This article is syndicated on: