基于模板参数类型的调用函数

新手上路,请多包涵

有两个“C”函数:

 void fooA(const char*);
void fooW(const wchar_t*);

然后是一个包装模板函数:

 template<typename _TChar>
void foo(const _TChar* str)
{
     // call fooA or fooB based on actual type of _TChar
     // std::conditional .. ?
         // fooA(str);
         // fooW(str);
}

如果调用者调用 foo("Abc") ,这个模板函数应该在编译时调用 fooA 。同样, foo(L"Abc") 应该最终调用 fooW

我怎么做?我想过使用 std::conditional 但做不到。

我不能使 fooAfooB 重载,因为这些是 C 函数。

原文由 Ajay 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 399
1 个回答

您可以将 所有 wchar_t 版本放在一个类模板中,比如 overloads 及其 char 在其专业化中的对应部分,如下所示:

 template<typename WideCharVersion>
struct overloads
{
    void foo(wchar_t const * arg)
    {
       FooW(arg);
    }
    //more wchar_t functions
};

template<>
struct overloads<std::false_type>
{
    void foo(char const * arg)
    {
       FooA(arg);
    }
    //more char functions
};

//a friendly alias!
template<typename T>
using is_wide_char = typename std::is_same<whar_t, T>::type;

然后您可以将它们用作:

 template<typename _TChar>
void foo(const _TChar* str)
{
    overloads<is_wide_char<_TChar>>::foo(str);
}


表达式 SFINAE 让一切变得简单!

另一种方法是使用 Expression SFINAE ,它不需要您编写类似 overloads 的任何内容,并且可以用更少的代码完成相同的工作:

 template<typename _TChar>
void foo(const _TChar* str)
{
    invokeOne(fooA, fooW, str);
}

然后你可以实现 invokeOne 为:

  template<typename F1, typename F2, typename ... Args>
 auto invokeOne(F1 f1, F2 f2, Args && ... args) -> decltype(f1(args...))
 {
     return f1(args...);
 }

 template<typename F1, typename F2, typename ... Args>
 auto invokeOne(F1 f1, F2 f2, Args && ... args) -> decltype(f2(args...))
 {
     return f2(args...);
 }

看看 在线演示

在这种方法中,您不必将重载添加到 overloads 类模板 及其 特化中。相反,您只需将它们作为参数传递给 invokeOne 它会为您调用正确的重载。

希望有帮助。

原文由 Nawaz 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题