使用SFINAE和void_t区分类型

Art*_*zuk 2 c++ c++14

我遇到了一些需要编写两个函数的情况,其中一个函数应该用原始类型调用std::string.另一个应该用其他类型调用.

到目前为止,我以工作解决方案结束

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";
}
Run Code Online (Sandbox Code Playgroud)

用法:

foo (1);
foo (1.2);
foo (std::string {"fsdf"});
foo (std::vector<int> {1, 2, 3});
foo (std::vector<std::string> {"a", "v", "c"});
Run Code Online (Sandbox Code Playgroud)

按预期生产:

string or primitive
string or primitive
string or primitive
other type
other type
Run Code Online (Sandbox Code Playgroud)

我的问题是:你知道更好地解决这类问题吗?

我不确定是否检查是否c_str()存在是我能得到的更好的选择.我知道我可能会编写一些包含原始类型的包装类,并且std::string会有一些category_t定义的值X,对于其他类型的值,Y并使用此类别区分这些组,但我仍然认为c_str()检查更方便.

Ric*_*ges 6

我不确定是否检查c_str()是否是我能得到的更好的选择.

理想情况下,你会检查你真正想要的东西.

这可以是一组已知类型或模板,也可以是一个概念.

此刻,你正在检查"具有返回一个指向字符常量一个c_str()成员函数的概念".

问题是,您的SFINAE功能需要什么概念?

如果它会使用该c_str()成员,那是合理的.但是,如果它将使用其他成员或字符串类型,您可能希望构建一个复合概念来描述您将要运用的接口部分.

当然,您可能只想确认它实际上是一个专业化std::string.除非你陈述用例,否则很难(不可能)告诉你.