I have 3 compilers disagreeing on the below C++14 code:
#include <type_traits>
template <typename P, typename F>
constexpr auto can_call(P* p, F&& f) -> decltype(f(p),std::true_type{}) { return {}; }
template <typename F>
constexpr std::false type can_call(void const*, F&&) { return {}; }
struct C {
C() { auto pc = can_call(this, [&](auto p) -> decltype(p->f(3)) {}); }
void f(int);
};
template <typename T>
struct CT {
CT() { auto ptc = can_call(this, [&](auto p) -> decltype(p->f(3)) {}); }
void f(T);
};
int main()
{
C oc;
auto pc = can_call(&oc, [&](auto p) -> decltype(p->f(3)) {});
CT<int> oct;
auto ptc = can_call(&oct, [&](auto p) -> decltype(p->f(3)) {});
}
clang++ 3.7 accepts it without a hitch.
g++ 4.9, 5.1, 5.2, 5.3 and trunk fail the CT<T>
constructor, with the message:
t.cpp: In instantiation of ‘CT<T>::CT() [with T = int]’:
t.cpp:24:11: required from here
t.cpp:16:61: error: base operand of ‘->’ has non-pointer type ‘auto:2’
CT() { auto ptc = can_call(this, [&](auto p) -> decltype(p->f(3)) {}); }
^
VisualStudio 2015 Community is the exact opposite of g++ and fails all lambdas, except the templated CT<T>
constructor, complaining that left of '->f'
must be a pointer. (I have not checked if perhaps it wrongly gets the std::false_type
result in the CT<T>
constructor.)
From this I have two questions:
- What is expected? I have tried to read the (draft C++17) standard from github, but to be honest I don't even know where to look, especially since the compilers disagrees a bit too much.
- Can the intended reflection be portably implemented in a different way? I want (not need) the functionality to improve compilation error messages from a library.
Aucun commentaire:
Enregistrer un commentaire