我试图尽可能简单地执行SFINAE重载,以便编写几种 getSize(s)
函数:一个返回 s.getSize()
,另一个 s.GetLength()
,然后我可能会添加 s.length()
等 .
不幸的是,此代码在MSVC 2015 Update 3上产生了奇怪的错误:
我错过了什么,或者这是一些编译问题?
template <typename T>
static size_t getSize(const T& string, decltype(&T::size) dummy = nullptr)
{
return string.size();
}
template <typename T>
static size_t getSize(const T& string, decltype(&T::GetLength) dummy = nullptr)
{
return static_cast<size_t>(string.GetLength());.
}
assert(SpellCheck::getSize(CString("123")) == 3); // .GetLength()
assert(SpellCheck::getSize(std::string("123")) == 3); // .size()
错误C2572:'SpellCheck :: getSize':重新定义默认参数:参数1错误C2535:'size_t SpellCheck :: getSize(const T&,unknown-type)':成员函数已定义或声明错误C2672:'拼写检查: :getSize':找不到匹配的重载函数错误C2893:无法专门化函数模板'size_t SpellCheck :: getSize(const T&,unknown-type)':注意:'T = ATL :: CStringT >>'
据我所知, getSize(CString())
与 getSize(std::string())
至少与 dummy
指针类型不同,因此它们的签名会有所不同,重载分辨率应该可以正常工作 .
任何人都可以建议我为什么抱怨一些 unknown-type
,好吗?
我设法通过这个奇怪的结构让它工作:
template <typename T>
static auto getSize(const T& string) -> decltype(string.size())
{
return string.size();
}
template <typename T>
static auto getSize(const T& string) -> decltype(static_cast<size_t>(string.GetLength()))
{
return static_cast<size_t>(string.GetLength());
}
令人惊讶的是,使用这样的汽车它工作正常 .
我也在gcc版本7.2.0(Ubuntu 7.2.0-8ubuntu3)上检查了这个代码,两种变体都可以正常工作 . 当然,为了测试实例化,我还为gcc实现了CString:
#ifdef _WIN32
#include <atlstr.h>
#else
struct CString
{
CString(const char*) {}
int GetLength() const { return 3; }.
};
#endif
那么,请建议我,我是否遗漏了某些内容或第一个示例触发了一些特定于MS的问题?
编辑:简化的第二个解决方案