免责声明:我认为给出的示例与名称解析有关,但这种假设可能是错误的。
有这样的代码:https://godbolt.org/z/bEEjP3x16
#include <functional>
int foo() { return 0; };
using Fn = decltype(foo);
template <typename T>
concept Function = std::is_function_v<T>;
template <typename T>
class TValue {};
template <Function F>
class TValue<F*> {
public:
F* data;
constexpr operator F* () const { return data; }
};
// ---------------------------------------
#define MYTEST
#ifdef MYTEST
template <Function F>
::std::function(TValue<F*>) -> ::std::function<F>;
#else
namespace std {
template <Function F>
function(TValue<F*>) -> function<F>;
}
#endif // MYTEST
// ---------------------------------------
int main() {
TValue<Fn*> v{&foo};
std::function f = std::function(v);
}
GCC 可以很好地编译它。但是 Clang 和 MSVC 给出编译错误。 (此外,MS 帮助表明错误 C2643 已过时https://learn.microsoft.com/en-us/cpp/error-messages/compiler-errors-2/compiler-errors-c2600-through-c2699?view=msvc-170)
如果你隐藏定义MYTEST
//#define MYTEST
编译将沿着分支进行
namespace std {
template <Function F>
function(TValue<F*>) -> function<F>;
}
那么所有 3 个编译器都会顺利完成工作。
这才是真正的问题。谁是对的?或者这根本与名称解析规则无关,还有其他事情发生吗?