使用类型特征简化wchar_t / char模板化函数的创建

时间:2012-03-07 09:56:35

标签: c++ templates traits

我一直在写一个win32文件系统库,我决定不使用TCHAR,而是想编写一个模板(仅限标题)库,它可以在char / wchar_t上工作,而不管编译器范围/窄选项。

这给我留下了两个问题:

  1. 我的库必须透明/有效地确定是否调用ANSI / Wide版本的windows函数(例如CreateFileA或CreateFileW),具体取决于模板的扩展方式。
  2. 我的库有时需要使用字符串文字,因此我需要一种方法将“字符串文字转换为”或“L”,而不会产生运行时成本或混淆逻辑。
  3. 我已经创建了我认为对这两个问题的合理优雅的解决方案,但我希望堆栈溢出社区告诉我是否存在与它们相关的任何隐藏成本/恶意。

    首先(解决1)因为我的模板类将T作为字符类型,所以我在类中的“detail”命名空间中创建了以下模板/宏:

    // Selector template to choose between W and A versions of win32 functions
    template<typename WF, typename AF> inline WF& select_w32func(AF &,        WF & pFuncW, wchar_t) { return pFuncW; }
    template<typename WF, typename AF> inline AF& select_w32func(AF & pFuncA, WF &,        char)    { return pFuncA; }
    template<typename T> inline T get_traits() { return NULL; }
    
    #define SELECT_W32FUNC(x)    auto x = detail::select_w32func(::##x##A, ::##x##W, detail::get_traits<T>());
    #define SELECT_W32FUNCS(x,y) auto x = detail::select_w32func(::x, ::y, detail::get_traits<T>());
    

    接下来(解决2)我创建了以下模板和宏:

    template<typename WC, typename AC> inline const WC* select_chartrait(const AC*,   const WC* b, wchar_t) { return b; }
    template<typename WC, typename AC> inline const AC* select_chartrait(const AC* a, const WC*,   char)    { return a; }
    template<typename WC, typename AC> inline const WC select_chartrait(const AC,     const WC b,  wchar_t) { return b; }
    template<typename WC, typename AC> inline const AC select_chartrait(const AC a,   const WC,    char)    { return a; }
    
    // Macro which allows string literals to be adapted by template parameter T
    #define _S(x) detail::select_chartrait((x), (L##x), detail::get_traits<T>())
    

    这允许我编写类的构造函数和成员函数,就好像我没有处理模板化参数一样,例如,下面的构造函数构造一个带有CSIDL特殊文件夹标识符的w32file对象,因为它是它的父元素: / p>

    basic_w32file(DWORD dwCSIDL, std::basic_string<T> & child) : m_name( MAX_PATH, ' ' )
    {
      SELECT_W32FUNC(PathCombine);
      SELECT_W32FUNCS(strlen, wcslen);
    
      basic_w32file<T> parent( getSystemDirectory ( dwCSIDL, _S(' ')));
      if (child == _S(".") || child == _S(".."))
        PathCombine(&m_name[0], parent.getAbsoluteName().c_str(), child.c_str());
      else
        PathCombine(&m_name[0], parent.getPath().c_str(), child.c_str());
    
      m_name.resize( strlen(&m_name[0]) );
    }
    

    如您所见,SELECT_W32FUNC宏会覆盖全局命名空间的PathCombine定义,并将其替换为函数的A或W版本的函数引用。 _S(“..”)将正确的字符串文字放在适当的位置。

    我的感觉是,这将是非常有效的,因为模板选择器函数将被内联并且基本上没有运行时逻辑,这意味着它们应该被优化到几乎没有,这是正确的假设吗?

0 个答案:

没有答案