You can put all your wchar_t versions in a class template, say overloads and their char counter-parts in its specialization as shown below:
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;
And then you can use them as:
template<typename _TChar>
void foo(const _TChar* str)
{
overloads<is_wide_char<_TChar>>::foo(str);
}
Expression SFINAE makes it easy!
Other way is to use Expression SFINAE which does not require to you write anything like overloads and does the same job with less code:
template<typename _TChar>
void foo(const _TChar* str)
{
invokeOne(fooA, fooW, str);
}
And then you can implement invokeOne as:
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...);
}
Have a look at the online demo.
In this approach, you don't have to add the overloads to the overloads class template and to its specialization. Instead you just pass them as arguments to invokeOne which calls the right overload for you.
Hope that helps.