I have simplified version of code:
#include <experimental/type_traits>
template<class T> using has_data_t = decltype(T::data());
template <class B> constexpr auto get_data() {
return std::experimental::is_detected_v<has_data_t, B>;
}
template <typename Topt> struct opt_base {
static constexpr bool i = get_data<Topt>();
//static constexpr auto j = get_data<Topt>(); // fail to compile
};
struct opt : public opt_base<opt> {
static int data() { return 7;}
};
int main() {
static_assert(std::experimental::is_detected_v<has_data_t, opt>);
}
This code compiles. But if you will uncomment commented line then assert fails. It was tested with GCC 7.1 and Clang 4.0.0. Compilation parameters: -std=c++1z -O3 -Wall. Demo
In this code:
static constexpr bool i = get_data<Topt>();
static constexpr auto j = get_data<Topt>();
Topt
(that is, opt
) isn't complete yet. So is_detected_v<has_data_t, opt>
is should be false
. But by the time we get to main
, opt
is complete. And so we'd expect is_detected_v<has_data_t, opt>
to be true
.
Having a template that when instantiated in different contexts yields different results means that your program is ill-formed, no diagnostic required. See [temp.point]:
A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.
The addition of j
doesn't really matter - it just happened to flip the switch that changed the order of the way the compiler chose to instantiate things. The program is ill-formed regardless of the presence of j
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With