是否可以一次多次进行许多重载/指定,如下面的代码所示。
我希望很清楚,我正在尝试实现什么,但是编译器并不这么认为。
#include <stdint.h>
struct IP_address
{
uint32_t value;
};
template<typename T> struct Unsigned_type {};
template<> struct Unsigned_type<uint8_t >{ typedef uint8_t type; };
template<> struct Unsigned_type<uint16_t>{ typedef uint16_t type; };
template<> struct Unsigned_type<uint32_t>{ typedef uint32_t type; };
template<> struct Unsigned_type<uint64_t>{ typedef uint64_t type; };
template<typename T> struct Signed_type {};
template<> struct Signed_type<uint8_t >{ typedef uint8_t type; };
template<> struct Signed_type<uint16_t>{ typedef uint16_t type; };
template<> struct Signed_type<uint32_t>{ typedef uint32_t type; };
template<> struct Signed_type<uint64_t>{ typedef uint64_t type; };
template<typename T>
T parse(const char*);
template <typename T>
typename Unsigned_type<T>::type parse(const char* str)
{
return 1;
}
template <typename T>
typename Signed_type<T>::type parse(const char* str)
{
return -1;
}
template <>
IP_address parse(const char* str)
{
IP_address result;
result.value = 0x08080808;
return result;
}
int main()
{
uint32_t parsed_uint = parse<uint32_t>("300");
int32_t parsed_int = parse<int32_t>("-1337");
IP_address parsed_ip = parse<IP_address>("8.8.8.8");
uint8_t should_throw = parse<uint8_t>("300");
return 0;
}
clang和gcc都告诉
call to 'parse' is ambiguous
,但是我不知道为什么,我已经明确指定了类型!请帮助我了解为什么它不能编译以及如何使其工作?顺便说一句,在这种情况下甚至可以不使用宏就不重复自己吗?根据要求编译错误。
test.cpp: In function ‘int main()’:
test.cpp:47:49: error: call of overloaded ‘parse<uint32_t>(const char [4])’ is ambiguous
47 | uint32_t parsed_uint = parse<uint32_t>("300");
| ^
test.cpp:22:3: note: candidate: ‘T parse(const char*) [with T = unsigned int]’
22 | T parse(const char*);
| ^~~~~
test.cpp:25:33: note: candidate: ‘typename Unsigned_type<T>::type parse(const char*) [with T = unsigned int; typename Unsigned_type<T>::type = unsigned int]’
25 | typename Unsigned_type<T>::type parse(const char* str)
| ^~~~~
test.cpp:31:31: note: candidate: ‘typename Signed_type<T>::type parse(const char*) [with T = unsigned int; typename Signed_type<T>::type = unsigned int]’
31 | typename Signed_type<T>::type parse(const char* str)
| ^~~~~
test.cpp:50:48: error: call of overloaded ‘parse<uint8_t>(const char [4])’ is ambiguous
50 | uint8_t should_throw = parse<uint8_t>("300");
| ^
test.cpp:22:3: note: candidate: ‘T parse(const char*) [with T = unsigned char]’
22 | T parse(const char*);
| ^~~~~
test.cpp:25:33: note: candidate: ‘typename Unsigned_type<T>::type parse(const char*) [with T = unsigned char; typename Unsigned_type<T>::type = unsigned char]’
25 | typename Unsigned_type<T>::type parse(const char* str)
| ^~~~~
test.cpp:31:31: note: candidate: ‘typename Signed_type<T>::type parse(const char*) [with T = unsigned char; typename Signed_type<T>::type = unsigned char]’
31 | typename Signed_type<T>::type parse(const char* str)
|
最佳答案
您不能部分专门化模板功能。但是您可以定义一个具有SFINAE调用运算符的类模板:
#include <type_traits>
template<typename T>
struct parse
{
template<class U = T>
std::enable_if_t<std::is_signed_v<U>, T> operator()(const char* str)
{
return -1;
}
template<class U = T>
std::enable_if_t<!std::is_signed_v<U>, T> operator()(const char* str)
{
return 1;
}
};
当
parse<T>
明确专用时,将进行模板参数替换。如果T
是,例如unsigned
,std::is_signed_v<T>
将是false
。这使编译器尝试对格式错误的std::enable_if_t<false, T>
进行专门化处理。值得庆幸的是,这发生在SFINAE的范围内:该定义被简单地忽略了,从而获得了未签名的版本。一点文件
std::is_signed
std::enable_if
演示版
将
parse
类重命名为parse_impl
,您可以定义一个辅助函数:template<class T>
auto parse(const char* arg)
{ return parse_impl<T>{}(arg); }
Full program
关于c++ - C++许多SFINAE样式的重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60001989/