如何检查类是否在C++ 11中指定了嵌套类定义或typedef?

Yun*_*ang 8 c++ templates typedef c++11

在我的项目中,我想实现一些现有更大类的模板代理类.现有的类是库类,因此无法修改它们.在大多数情况下,客户端不知道对象是代理类或更大类的实例.但是,在某些情况下,客户必须知道详细的课程信息.由于代理类本身就是一个模板类,我不认为通过类名简单的函数重载可以解决这个问题.我认为可能的解决方案是在代理类中添加内部嵌套类或typedef,并且客户端检查是否存在此类/ typedef以获取类信息.我的问题是:如何检查类是否在C++ 11中指定了嵌套类定义或typedef?

以下代码显示了一个示例:

#include <iostream>
#include <functional>
#include <string>
#include <vector>
#include <type_traits>

typedef std::string CBig1;  //  use string for demonstration
typedef std::string CBig2;  //  use string for demonstration

//class CBig1;   // the bigger class 1, codes of which can not be changed
//class CBig2;   // the bigger class 2, codes of which can not be changed

template <typename _Big, typename _Other>
class CProxy
{
public:
    struct proxy_tag { };
};

//  how to implement this ?
//  the proxy traits class, if defined _T::proxy_tag, the ``type'' will be std::true_type, otherwise the ``type'' will be std::false_type
template <typename _T>
struct is_proxy
{
    //typedef std::true_type type;
    //typedef std::false_type type;
};

template <typename _T>
void ClientHelp(const _T& t, std::false_type)
{
    //  process real class
    std::cerr << "real class" << std::endl;
}

template <typename _T>
void ClientHelp(const _T& t, std::true_type)
{
    //  process proxy class
    std::cerr << "proxy class" << std::endl;
}

template <typename _T>
void Client(const _T& t)
{
    ClientHelp(t, typename is_proxy<_T>::type());
}

int main(int argc, char* argv[])
{
    CBig1 b;
    CProxy<CBig1, int> p;
    Client(b);
    Client(p);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如何实现traits类is_proxy

Joe*_*cou 20

您可以使用轻量级类型分类习惯用法

template<class T, class R = void>  
struct enable_if_type { typedef R type; };

template<class T, class Enable = void>
struct test : std::false_type {};

template<class T>
struct test<T, typename enable_if_type<typename T::is_proxy_tag>::type> : std::true_type
{};

template <typename _Big, typename _Other>
class CProxy
{
  public:
  typedef void is_proxy_tag;
};
Run Code Online (Sandbox Code Playgroud)

因此,要使类成为代理,只需添加它

typedef void is_proxy_tag;
Run Code Online (Sandbox Code Playgroud)

并且SFINAE enable_if_type将选择正确true_type/ false_type专业化

请注意,使用boost::mpl::true_而不是使用std::true_type此解决方案适用于C++ 03.


Mat*_* M. 12

作为C++ 03版本的补充,在C++ 11中,您将获得decltype:

template <typename T>
auto is_proxy(T const&) -> decltype(T::proxy_tag{}, std::true_type{}) {
  return std::true_type{};
}

std::false_type is_proxy(...) { return std::false_type{}; }
Run Code Online (Sandbox Code Playgroud)

你的实现Client变成:

template <typename T>
void Client(T const& t) {
  ClientHelp(t, is_proxy(t));
}
Run Code Online (Sandbox Code Playgroud)

甜,不是吗?

  • @MichaelWild:它使用序列运算符`,`.通常在循环条件下找到它,例如`for(;; ++ i,++ e)`,序列运算符从左到右计算两个操作数并返回右操作数的结果.它也可以链接:`++ a,++ b,++ c`将返回`++ c`的结果,并且保证评估的顺序是`++ a`*然后*`+ + b`*然后*`++ c`.这里唯一的用途是在左侧部分使用SFINAE检查,在右侧使用表达式产生所需的返回类型.您可以尝试将整个事物包装在另一层括号中. (3认同)