I faced some situation where I have to write two functions, one of them should be invoked with primitive types and std::string
. The other one should be called with other types.
So far I ended with working solution:
template <typename...>
struct Void_t_helper {
using type = void;
};
template <typename... Ts>
using Void_t = typename Void_t_helper<Ts...>::type;
template <typename T, typename = void>
struct Is_string : std::false_type {};
template <typename T>
struct Is_string<T, Void_t<decltype (std::declval<T> ().c_str ())>> : std::is_same<decltype (std::declval<T> ().c_str ()), const char*>::type {};
template <typename T>
std::enable_if_t<Is_string<T>::value || std::is_arithmetic<T>::value, void> foo (T) {
std::cout << "string or primitive\n";
}
template <typename T>
std::enable_if_t<!Is_string<T>::value && !std::is_arithmetic<T>::value, void> foo (T) {
std::cout << "other type\n";
}
And the usage:
foo (1);
foo (1.2);
foo (std::string {"fsdf"});
foo (std::vector<int> {1, 2, 3});
foo (std::vector<std::string> {"a", "v", "c"});
produces as expected:
string or primitive
string or primitive
string or primitive
other type
other type
My question is: Do you know better solution to this kind of problem?
I am not really sure if checking if c_str()
exists is the better option I can get. I am aware that I could probably write some wrapper class that for primitive types and std::string
would have some category_t
defined with value X
, and for other types value Y
and distinguish between these groups using this category, but still I think that c_str()
checking is more convenient.