我遇到了必须编写两个函数的情况,其中一个函数应该用原始类型和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";
}

以及用法:
foo (1);
foo (1.2);
foo (std::string {"fsdf"});
foo (std::vector<int> {1, 2, 3});
foo (std::vector<std::string> {"a", "v", "c"});

产生预期的结果:
string or primitive
string or primitive
string or primitive
other type
other type

我的问题是:您知道更好的解决方案吗?

我不确定如果检查c_str()是否存在是我可以获得的更好选择。我知道我可能会写一些包装器类,对于原始类型和std::string,将使用值category_t定义一些X,对于其他类型,将值Y定义为,并使用该类别区分这些组,但我仍然认为c_str()检查更多方便。

最佳答案



理想情况下,您将检查自己的实际需求。

那可以是一组已知的类型或模板,也可以是一个概念。

目前,您正在检查“具有c_str()成员函数的概念,该函数返回指向常量chars的指针”。

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

如果它将使用c_str()成员,那是合理的。但是,如果要使用字符串的其他成员或类型,则可能要构建一个复合概念来描述将要使用的接口(interface)的各个部分。

当然,您可能只想确认它实际上是std::string的特殊化。除非陈述用例,否则很难(不可能)说出来。

关于c++ - 使用SFINAE和void_t区分类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46756319/

10-11 22:53
查看更多