Info
-
Did you know wrapping an unqualified function name in parentheses suppresses argument-dependent lookup?
Example
namespace adl {
struct foo {};
void bar(foo) {}
}
int main() {
adl::foo foo;
bar(foo); // OK, ADL
(bar)(foo); // error: no ADL
}
Puzzle
- Can you implement function bar which returns { 0: if it's not ADL call, 42: if it's a qualified call; ambigious error: if it's an ADL call }?
#include <cassert>
//TODO
int main() {
static_assert([](auto foo) { return requires { adl::bar(foo); }; }(adl::foo{}));
assert(42 == adl::bar(adl::foo{}));
static_assert([](auto foo) { return requires { ::bar(foo); }; }(adl::foo{}));
assert(0 == ::bar(adl::foo{}));
static_assert([](auto foo) { return requires { (bar)(foo); }; }(adl::foo{}));
assert(0 == (bar)(adl::foo{}));
static_assert(not [](auto foo) { return requires { bar(foo); }; }(adl::foo{}));
}
Solutions
namespace adl {
struct foo {};
constexpr auto bar(foo) -> int { return 42; }
}
constexpr auto bar(adl::foo) -> int { return 0; }
namespace adl {
struct foo {};
[[nodiscard]] constexpr auto bar(const foo) noexcept -> int { return 42; }
} // namespace adl
[[nodiscard]] constexpr auto bar(const adl::foo) noexcept -> int { return 0; }