| 1 | namespace detail { |
| 2 | template <typename T> struct Quux {}; |
| 3 | } // namespace detail |
| 4 | |
| 5 | using FuncPtr = detail::Quux<double> (*(*)(int))(float); |
| 6 | |
| 7 | struct Foo { |
| 8 | template <typename T> void foo(T arg) const noexcept(true) {} |
| 9 | |
| 10 | template <int T> void operator<<(int) {} |
| 11 | |
| 12 | template <typename T> FuncPtr returns_func_ptr(detail::Quux<int> &&) const noexcept(false) { return nullptr; } |
| 13 | }; |
| 14 | |
| 15 | namespace ns { |
| 16 | template <typename T> int foo(char const *str) noexcept(false) { return 0; } |
| 17 | template <typename T> int foo(T t) { return 1; } |
| 18 | |
| 19 | template <typename T> FuncPtr returns_func_ptr(detail::Quux<int> &&) { return nullptr; } |
| 20 | } // namespace ns |
| 21 | |
| 22 | int bar() { return 1; } |
| 23 | |
| 24 | namespace { |
| 25 | int anon_bar() { return 1; } |
| 26 | auto anon_lambda = [] {}; |
| 27 | } // namespace |
| 28 | |
| 29 | __attribute__((always_inline)) int inlined_foo(const char *str) { |
| 30 | if (bool b = bar()) |
| 31 | return 1; |
| 32 | return 2; |
| 33 | } |
| 34 | |
| 35 | int main() { |
| 36 | ns::foo<decltype(bar)>(t: bar); |
| 37 | ns::foo<decltype(bar)>(str: "bar" ); |
| 38 | ns::foo(t: anon_lambda); |
| 39 | ns::foo(t: anon_bar); |
| 40 | ns::foo<decltype(&Foo::foo<int(int)>)>(str: "method" ); |
| 41 | ns::returns_func_ptr<int>(detail::Quux<int>{}); |
| 42 | Foo f; |
| 43 | f.foo(arg: anon_bar); |
| 44 | f.operator<< <(2 > 1)>(0); |
| 45 | f.returns_func_ptr<int>(detail::Quux<int>{}); |
| 46 | inlined_foo(str: "bar" ); |
| 47 | return 0; |
| 48 | } |
| 49 | |