5

目前,我有一个这样的函数模板,可以将 a 转换vector为 a string(只是一个自然字符串,用逗号分隔元素):

//the type T must be passable into std::to_string
template<typename T>
std::string vec_to_str(const std::vector<T> &vec);

如您所见,这仅适用于其元素可以传递给内置std::to_string函数的向量(例如int,double等)

记录允许的评论是否被认为是一种好习惯T?如果没有,我该怎么办?是否有可能以更好的方式执行此操作?

4

3 回答 3

4

使用static_assert和一些表达式 SFINAE,你可以得到一个很好的编译时错误消息:

template<typename T>
constexpr auto allowed(int) -> decltype(std::to_string(std::declval<T>()), bool())
{
    return true;
}

template<typename>
constexpr bool allowed(...)
{
    return false;
}

template<typename T>
std::string vec_to_str(const std::vector<T>& vec)
{
    static_assert(allowed<T>(0), "Invalid value type.");
    return "";
}

struct foo {};

int main()
{
    std::vector<int> v_int;
    vec_to_str(v_int);

    std::vector<foo> v_double;
    vec_to_str(v_double);       // static_assert fires here
}
于 2012-12-14T22:55:18.670 回答
2

由于std::to_string是 C++11 功能,我猜您可能对 C++11 解决方案持开放态度。在这种特殊情况下,您可以以 sfinae 方式使用尾随返回类型:

template <typename T>
auto vec_to_str(const std::vector<T>& vec) -> decltype(std::to_string(std::declval<T>()));

如果值类型不适用于to_string. 但是,这不一定是记录和执行规则的最令人赏心悦目的方式。上面的 Sfinae 技巧可能还有一个 C++11 之前的版本,但它不会更漂亮。

一般来说,我会说在评论中简单地记录它是很好的(可能带有一个 doxygen 标签,比如\tparam)。如果需要,您可以使用 Boost.Concept-Check 风格的概念检查机制。

作为旁注,对于这种特定情况,我可能会建议您依赖于std::ostream operator <<而不是to_string函数,因为自定义类型(例如,2D 矢量或其他东西)更有可能配备重载以输出到溪流。

于 2012-12-14T22:52:25.877 回答
0

概念出现之前,您可以使用decltype匿名类型参数:

template<typename T,
  typename = decltype(std::to_string(std::declval<T>()))>
std::string vec_to_str(const std::vector<T> &vec);
于 2012-12-14T22:46:35.670 回答