gpt4 book ai didi

c++ - 使用 SFINAE 与 GCC 检测方法

转载 作者:行者123 更新时间:2023-12-01 14:18:12 26 4
gpt4 key购买 nike

我在使用 SFINAE 概念检测某个类是否具有某些编译器(最相关的 GCC)的特定模板方法时遇到了问题。考虑下面的代码。它按预期与 MSVC 一起编译和工作;然而,当我用 GCC 编译相同的代码时,它会提示 std::vector<double>没有序列化方法。当然,该方法不存在这一事实是真实的,但我预计这会导致替换失败,并且编译器会确定其他不太专业的回退是最合适的。我是否遗漏了有关 SFINAE 的信息,或者这是 GCC 的错误?

#include <iostream>
#include <utility>
#include <vector>

class SerializerBase
{
public:
SerializerBase() {}
};

template<typename T>
struct has_serialize
{
template<typename C>
static constexpr auto test(...) -> std::false_type;
/// Note: this is where the compiler complains about the .serialize method
/// during substitution.
template<typename C>
static constexpr auto test(int)
-> decltype(std::declval<T>().serialize(std::declval<SerializerBase&>()), std::true_type());

using result_type = decltype(test<T>(0));
static const bool value = result_type::value;
};

class Serializer : public SerializerBase
{
public:
Serializer() {}

template<typename T,
typename std::enable_if<!has_serialize<T>::value, T>::type* = nullptr>
void operator()(const T& v)
{
std::cout << "fallback called" << std::endl;
}

template<typename T,
typename std::enable_if<has_serialize<T>::value, T>::type* = nullptr>
void operator()(const T& v)
{
v.serialize(*this);
}
};

struct Foo
{
template<typename SerializerType>
void serialize(SerializerType& s) const
{
std::cout << "serialize called" << std::endl;
}
};

int main()
{
Serializer s;
std::vector<double> v;
Foo f;
s(v);
s(f);

return 0;
}

最佳答案

如果其他人遇到类似的错误/误解,我的错误(由 n. 'pronouns' m. 恰本地指出)是在 has_serialize::test 中使用了错误的类型.从我可以推断(以我的天真)是为了

template<typename T>
struct has_serialize
{
// ...
template<typename C>
static constexpr auto test(int)
-> decltype(std::declval<T>().serialize(std::declval<SerializerBase&>()), std::true_type());
// ...
};

模板C没有出现在 has_serialize::test 中,因此 GCC 不提供替换失败的机会。因此,GCC 尝试评估 std::declval<T>().serialize(...)显然在 T = std::vector<double> 时抛出错误.如果T替换为 C在这一行中,然后编译器将其识别为替换失败并确定签名不合适。

此外,正如 Maxim Egorushkin 指出的那样,有可能 T::serialize可能会返回重载 operator, 的用户定义类型.为了改善(尽管不太可能)潜在的错误,代码应该是:

template<typename T>
struct has_serialize
{
// ...
template<typename C>
static constexpr auto test(int)
-> decltype(static_cast<void>(std::declval<C>().serialize(std::declval<SerializerBase&>())), std::true_type());
// ...
};

关于c++ - 使用 SFINAE 与 GCC 检测方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63253287/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com