我已经用测试用例编写了这种类型特征:
template <typename T, typename = int>
struct is_serializable: false_type {};
template <typename T>
struct is_serializable<
T,
enable_if_t<
is_same_v<
decltype(declval<T>().serialize(declval<gsl::span<uint8_t>>())),
gsl::span<uint8_t>
>
>
> : true_type {};
template <typename T>
constexpr bool is_serializable_v = is_serializable<T>::value;
struct Serialize {
gsl::span<uint8_t> serialize(gsl::span<uint8_t> input) {
return input
}
};
static_assert(is_serializable_v<Serialize>, "***");
这个效果很好。
然后我通过添加模板参数来选择字节序来扩展整个内容,如下所示:
enum class Endian {
LITTLE,
BIG
}
template <typename T, typename = int>
struct is_serializable: false_type {};
template <typename T>
struct is_serializable<
T,
enable_if_t<
is_same_v<
decltype(declval<T>().serialize<Endian::LITTLE>(declval<gsl::span<uint8_t>>())),
gsl::span<uint8_t>
> &&
is_same_v<
decltype(declval<T>().serialize<Endian::BIG>(declval<gsl::span<uint8_t>>())),
gsl::span<uint8_t>
>
>
> : true_type {};
template <typename T>
constexpr bool is_serializable_v = is_serializable<T>::value;
struct Serialize {
template <Endian endian>
gsl::span<uint8_t> serialize(gsl::span<uint8_t> input) {
return input
}
};
static_assert(is_serializable_v<Serialize>, "***");
这不再起作用了。类型特征返回 false。
为了看看发生了什么,我尝试过
static_assert(
is_same_v<
decltype(declval<Serialize>().serialize<Endian::LITTLE>(declval<gsl::span<uint8_t>>())),
gsl::span<uint8_t>
> &&
is_same_v<
decltype(declval<Serialize>().serialize<Endian::BIG>(declval<gsl::span<uint8_t>>())),
gsl::span<uint8_t>
>,
"***"
)
这与特征中的enable_if参数是一样的,这给了我
true
。
但如果这是 true
,则 is_serialized_v 类型特征也应该是 true
,不是吗?我现在有多傻?
免责声明:
std::
前缀。我添加了例如using std::declval;
等位于文件开头。type
的默认enable_if
是void
。
仅当主模板的第二个模板参数为
void
: 时,才可以使用您的模板特化
template <typename T, typename = void>
struct is_serializable: false_type {};
你需要使用这样的语法:
decltype(declval<T>().template serialize<Endian::LITTLE>
告诉编译器
<Endian
左尖括号打开模板参数列表,而不是较少运算符。