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

时间:2016-01-04 07:39:44

标签: c++ typetraits

有没有办法检查class是否有typedef哪个适用于private typedef

以下代码在VS2013中有效,但在ideone's 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 trait)有效,但所有POD类型只是所有类型的子集,支持此序列化。

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

基本决定类是否可以原始序列化的事物是其成员(没有反射,成员不能自动枚举和检查,因此用户必须提供此类信息)。典型的类看起来像这样:

class
  public
    ctor-dtor
    methods
  private
    methods
    members

我希望用户允许写ALLOW_RAW_SERIALIZE尽可能靠近成员,因此当他们更改某些成员时,忘记更新ALLOW_RAW_SERIALIZE的机会就会更少(删除它。当它&# 39; s不再有效)

这就是我想检查private typedef

的原因

由于它可以替代反射并采用整体类型并编写它,所以我不会像打破封装那样堕落......

2 个答案:

答案 0 :(得分:1)

<强>更新

好的,做了一点研究。

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

但是,我不确定如果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的书:&#34;现代C ++设计:应用的通用编程和设计模式&#34;,第2.10节类型特征:

  

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

所以,它可以&#34;好的&#34;如果你愿意,可以自己动手。

但是,即使他[来自Loki]的TypeTraits再次提及的东西也没有与你正在做的事情相匹配。

由于stdBoost都没有任何内容,因此问题变为&#34;标准是什么?&#34; [从你的角度来看]。可能有&#34; fludger&#34; c ++ traits库在某个地方有一个实现,但是会被认为是&#34;标准&#34;? YMMV

然而,一两个问题:

为什么会这样做?有什么用?基类中受保护的typedef怎么样?

并且,这似乎需要了解课堂的私人部分,并且不会违反数据隐藏&#34;或封装[没有friend某种声明]?

所以,如果最后一个问题属实,那么可能的[IMO]答案是没有标准的方法来做到这一点,因为它不是应该<的东西/ em>在标准库中做。

旁注:这是被投票的部分(在我真正理解这个问题之前)。我相信我已经在上面宣告自己无罪。所以,忽略下面的答案。

使用class时,默认可见性为private。使用struct,它是public

所以,要么:

struct Foo

或者:

class Foo
{
    public:
    typedef int TD;
};

当然,这是假设您想要 TDpublic

答案 1 :(得分:0)

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

#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);
}