In this program, extract1 has a different output from all the rest. Why is that?
Specifically, why extract1 and extract2 have different outputs?
Can be reproduced in GCC, Clang, ICC, ZapCC, EllCC. But it cannot be reproduced in MSVC.
| #include <iostream> | |
| template <class T> | |
| struct dispatch {}; | |
| // --- extract 1 --- | |
| namespace test1 | |
| { | |
| template <class T> | |
| void do_extract1(dispatch<T>) | |
| { | |
| std::cerr << "T\n"; | |
| } | |
| template <class T> | |
| void do_extract1(dispatch<T const&>) | |
| { | |
| std::cerr << "T const&\n"; | |
| do_extract1(dispatch<T>{}); | |
| } | |
| template <class T> | |
| void do_extract1(dispatch<T const*>) | |
| { | |
| std::cerr << "T const*\n"; | |
| do_extract1(dispatch<T const&>{}); | |
| } | |
| inline void do_extract1(dispatch<char const&>) | |
| { | |
| std::cerr << "char const&\n"; | |
| do_extract1(dispatch<std::string const&>{}); | |
| } | |
| template <class T> | |
| void extract1() | |
| { | |
| do_extract1(dispatch<T>{}); | |
| } | |
| } | |
| // --- extract 2 --- | |
| template <class T> | |
| void do_extract2(dispatch<T>) | |
| { | |
| std::cerr << "T\n"; | |
| } | |
| template <class T> | |
| void do_extract2(dispatch<T const&>) | |
| { | |
| std::cerr << "T const&\n"; | |
| do_extract2(dispatch<T>{}); | |
| } | |
| template <class T> | |
| void do_extract2(dispatch<T const*>) | |
| { | |
| std::cerr << "T const*\n"; | |
| do_extract2(dispatch<T const&>{}); | |
| } | |
| inline void do_extract2(dispatch<char const&>) | |
| { | |
| std::cerr << "char const&\n"; | |
| do_extract2(dispatch<std::string const&>{}); | |
| } | |
| template <class T> | |
| void extract2() | |
| { | |
| do_extract2(dispatch<T>{}); | |
| } | |
| // --- extract 3 --- | |
| namespace test3 | |
| { | |
| template <class T> | |
| void do_extract3(dispatch<T>) | |
| { | |
| std::cerr << "T\n"; | |
| } | |
| template <class T> | |
| void do_extract3(dispatch<T const&>) | |
| { | |
| std::cerr << "T const&\n"; | |
| do_extract3(dispatch<T>{}); | |
| } | |
| // Adjusted orders here | |
| inline void do_extract3(dispatch<char const&>) | |
| { | |
| std::cerr << "char const&\n"; | |
| do_extract3(dispatch<std::string const&>{}); | |
| } | |
| template <class T> | |
| void do_extract3(dispatch<T const*>) | |
| { | |
| std::cerr << "T const*\n"; | |
| do_extract3(dispatch<T const&>{}); | |
| } | |
| template <class T> | |
| void extract3() | |
| { | |
| do_extract3(dispatch<T>{}); | |
| } | |
| } | |
| // --- extract 4 --- | |
| struct test4 | |
| { | |
| template <class T> | |
| static void do_extract4(dispatch<T>) | |
| { | |
| std::cerr << "T\n"; | |
| } | |
| template <class T> | |
| static void do_extract4(dispatch<T const&>) | |
| { | |
| std::cerr << "T const&\n"; | |
| do_extract4(dispatch<T>{}); | |
| } | |
| static inline void do_extract4(dispatch<char const&>) | |
| { | |
| std::cerr << "char const&\n"; | |
| do_extract4(dispatch<std::string const&>{}); | |
| } | |
| template <class T> | |
| static void do_extract4(dispatch<T const*>) | |
| { | |
| std::cerr << "T const*\n"; | |
| do_extract4(dispatch<T const&>{}); | |
| } | |
| template <class T> | |
| static void extract4() | |
| { | |
| do_extract4(dispatch<T>{}); | |
| } | |
| }; | |
| int main() | |
| { | |
| std::cerr << "---- extract 1 ----\n"; | |
| test1::extract1<char const*>(); | |
| std::cerr << "---- extract 2 ----\n"; | |
| ::extract2<char const*>(); | |
| std::cerr << "---- extract 3 ----\n"; | |
| test3::extract3<char const*>(); | |
| std::cerr << "---- extract 4 ----\n"; | |
| test4::extract4<char const*>(); | |
| } | |
Case solved: ADL