I encountered a problem relating to return type deduction for methods of nested classes. After some digging, I narrowed down the problem to a simplified version as following:
#include <type_traits>
struct Alive {};
template<typename T>
auto is_alive_impl(...) -> void;
template<typename T>
auto is_alive_impl(int) -> decltype(std::declval<T>().operator()());
template<typename T>
struct is_alive : std::is_same<decltype(is_alive_impl<T>(0)), Alive> {};
struct Box {
struct Cat {
auto
operator()() {
return Alive{};
}
};
static constexpr auto value = is_alive<Cat>::value; // (1)
};
int main() {
static_assert(is_alive<Box::Cat>::value); // (2)
}
struct is_alive check if a class has operator() which return an Alive instance using function overloading trick.
Without line (1), the static_assert at (2) return true and the code compiles as expected.
However, I do not understand why adding line (1) make line (2) failed. It seems like I looked into the box and somehow killed the cat.
So here is my questions:
- Why at line (1),
valueis false? - Why adding line (1) make line (2) failed?
It would be great if you can refer to parts of the Standard which dictate that behaviors.