是否可以一次执行许多重载/规范,如下面的代码所示。我希望很清楚,我正在尝试实现什么,但是编译器却不这么认为。
#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
将std::enable_if
类重命名为SFINAE,您可以定义一个辅助函数:
parse
parse_impl
您的问题比模板问题更多是重载问题。