I have a problem that is very similar to this one .
In short, I have a magic method that is noexcept if the other method is noexcept .
It is strange that this “other method” has two overloads, and the compiler chooses the second overload to determine magic noexcept -ness.
However, when magic is called later, the overload is called first , but noexcept -ness magic remains unchanged!
Here is the wandbox link
From what I understand:
noexcept(magic(dummy2{})) callsnoexcept(noexcept(adl_caller(...)) , which returns toadl_caller(..., priority_tag<0>) noexcept , since user_method(dummy2) not known to the compiler at this point.
Fair, however, as user_method(dummy2) calls 3 lines above? Is this provided by the standard?
Sorry if I'm not clear enough.
#include <iostream> template <unsigned N> struct priority_tag : priority_tag<N - 1> {}; template <> struct priority_tag<0> {}; template <typename T> auto adl_caller(T t, priority_tag<1>) noexcept(noexcept(user_method(t))) -> decltype(user_method(t)) { std::cout << "first adl_caller overload" << std::endl; user_method(t); } // tricky noexcept ... template <typename T> void adl_caller(T, priority_tag<0>) noexcept { std::cout << "second adl_caller overload" << std::endl; } template <typename T> void magic(T t) noexcept(noexcept(adl_caller(t, priority_tag<1>{}))) { adl_caller(t, priority_tag<1>{}); } struct dummy {}; struct dummy2 {}; // un-commenting this line makes the above call to cout print '0' // void user_method(dummy2); void user_method(dummy) { // user_method(dummy2) is declared after this point // this line prints '1', since magic falls back to the second adl_caller overload std::cout << "noexcept?: " << noexcept(magic(dummy2{})) << std::endl; std::cout << "dummy method called" << std::endl; // however, the first adl_caller overload is called here ... magic(dummy2{}); } void user_method(dummy2) { std::cout << "dummy2 method called" << std::endl; } int main() { magic(dummy{}); }
c ++ c ++ 11 noexcept templates argument-dependent-lookup
Dante
source share