Skip to content

Instantly share code, notes, and snippets.

@cjxgm
Created November 29, 2019 08:11
Show Gist options
  • Save cjxgm/126dc938494dacf3e36f63d3588b4de1 to your computer and use it in GitHub Desktop.
Save cjxgm/126dc938494dacf3e36f63d3588b4de1 to your computer and use it in GitHub Desktop.
Overload Resolution Anomaly

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*>();
}
@cjxgm
Copy link
Author

cjxgm commented Dec 11, 2019

Case solved: ADL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment