関数オブジェクトは、オーバーロードの解決中に通常の関数とは異なる方法で処理されますか? もしそうなら、どのように?
関数を同等に呼び出し可能な関数オブジェクトに置き換えると、コードの意味が変わる次のケースに遭遇しました。
#include <iostream>
namespace N
{
enum E { A, B };
void bar(E mode) { std::cout << "N::bar\n"; }
}
template <typename... Args>
void bar(Args&&... args) { std::cout << "global bar\n"; }
int main()
{
bar(N::A);
}
ここでの出力は「N::bar」です。これまでのところ、N::bar は ADL によって検出されており、N::bar とグローバル バーの両方が完全に一致しており、N::bar はテンプレートではないため優先されています。
しかし、グローバル バーを関数オブジェクトに変更すると、次のようになります。
#include <iostream>
namespace N
{
enum E { A, B };
void bar(E mode) { std::cout << "N::bar\n"; }
}
struct S
{
template <typename... Args>
void operator()(Args&&... args) { std::cout << "global bar\n"; }
};
S bar;
int main()
{
bar(N::A);
}
出力は「グローバル バー」になりました。違いはなぜですか?