检查类是否具有 typedef(私有或其他)的特征

Trait which checks whether class has typedef (private or other) or not

本文关键字:其他 特征 是否 typedef 检查      更新时间:2023-10-16

有没有办法检查class是否有甚至适用于private typedeftypedef

以下代码在VS2013中有效,但在ideone的gcc上失败

template<typename T>
struct to_void
{
    typedef void type;
};
class Foo
{
    typedef int TD;
};
template <typename T, typename dummy = void>
struct has_TD : std::false_type {};
template <typename T>
struct has_TD<T, typename to_void<typename T::TD>::type > : std::true_type{};
int main()
{
    std::cout << std::boolalpha << has_TD<Foo>::value << std::endl;
}

编辑 - 为什么我想要这个

我有自定义序列化系统,可以序列化任意类型。当它的行为必须不同时,它有几个重载(例如字符串(。对于其余类型,它只是将值写入内存。如果我有组合类型,我有时也可以写入内存(保存和加载发生在相同的架构上,使用相同的编译器编译,因此填充将是相同的,等等(。例如,此方法对 POD 类型(std::is_pod 特征(有效,但所有 POD 类型只是所有类型的子集,支持此序列化。

所以我基本上有模板化函数write<T>它只写入sizeof(T)字节(原始序列化(......但我不希望错误地调用它,我希望用户在他们的类中明确地说:"这个类/结构可以原始序列化"(。我这样做的方式是一个宏ALLOW_RAW_SERIALIZE,它定义了一些可以通过 trait 检查的 typedef。如果类 MyClass 不包含 typedef,则调用write(myClassInstance)将产生编译器错误。

基本上决定类是否可以原始序列化的东西是它的成员(没有反射,成员不能自动枚举和检查,所以用户必须提供这样的信息(。 典型的类如下所示:

class
  public
    ctor-dtor
    methods
  private
    methods
    members

我希望用户允许写ALLOW_RAW_SERIALIZE尽可能接近成员,所以当他们更改某些成员时,忘记更新ALLOW_RAW_SERIALIZE的机会较小(当它不再有效时将其删除(

所以这就是为什么我想检查一个private typedef

由于它是反射的替代品,并且采用整个类型并编写它,因此我不会像打破封装之类的那样陷入困境......

更新:

好的,做了一些研究。

仅供参考,ideone没有编译的[可能]原因是您正在做的事情需要-std=c++11[或更高]。 在添加之前,我遇到了类似的错误。 但是,我不得不使用clang++因为如果TD g++编译时仍然private问题。

但是,我不确定这是否有效,因为如果TD是公开的,则打印真实的唯一组合。 所有其他公共/私人和更改TD TF都产生了错误。 也许VS2013可以工作[为什么?],但另外两个编译器在编译或运行时结果中存在问题 - YMMV。

你正在做的事情的基础是std::integral_constant[自 c++11 以来]。 对于您正在做的事情,似乎没有标准的推导。 也就是说,从 http://www.cplusplus.com/reference/type_traits/integral_constant/开始,[左侧]的类型特征列表没有与您的用例 [AFAICT] 匹配的内容。

Boost.TypeTraits也没有任何东西可以匹配[再次,AFAICT]。

摘自Andrei Alexandrescu的书:"现代C++设计:通用编程和设计模式应用",第2.10节类型特征:

通常,您将编写自己的特征模板和类,因为您的通用代码需要它们。但是,某些特征适用于任何类型。它们可以帮助泛型程序员更好地定制模板代码以适应类型的功能。

因此,如果您愿意,可以自己滚动

但是,即使是他(来自洛基(谈论的TypeTraits,也没有任何东西与你正在做的事情相匹配。

既然stdBoost都没有任何东西,那么问题就变成了"什么是标准?[从你的角度来看]。 可能在某个地方有"fludger"c++ 特征库有一个实现,但这会被认为是"标准"吗? 扬子晚报

但是,一两个问题:

为什么要这样做? 它有什么用? 基类中受保护的类型定义呢?

而且,这

似乎需要了解类的私有部分,这难道不是违反"数据隐藏"或封装[没有某种friend声明]吗?

因此,如果最后一个问题是真的,那么可能的答案是没有标准的方法可以做到这一点,因为这不是标准库中应该做的事情。


旁注:这是被否决的部分(在我[真正]理解这个问题之前(。 我相信我已经在上面无罪释放了自己。 所以,忽略下面的答案。

使用class时,默认可见性为 private 。 有了struct,就public了。

因此,要么执行以下操作:

struct Foo

或:

class Foo
{
    public:
    typedef int TD;
};

当然,这是假设您希望TD public

如果您只需要编译时检查,那么以下代码应该可以:

#include <iostream>
class Foo
{
    typedef int TD;
    template<typename T> friend class has_TD;
};
template <typename T>
struct has_TD
{
    typedef typename T::TD type;
};
template <typename T, typename has_TD<T>::type = 0>
void write(const T& /*data*/)
{
    std::cout << "serialize" << std::endl;
}
int main()
{
    Foo foo;
    write(foo);
}
相关文章: