鉴别添加剂类型?

时间:2016-01-21 07:55:44

标签: c++ templates

我在泛型编程中的第一步包括编写一个简单的函数,该函数累积作为参数传递的向量的总和。问题在于,该函数应仅适用于具有合理值的值的类型。

代码很简单:

template <typename T>
T accumulate_sum (const std::vector<T>& v) {
    // check for type and decide whether to sum or return nothing

    T sum = v[0];
    for (size_t i = 1; i < v.size(); ++i) sum += v[i];
    return sum;
} 

问题是如何区分添加剂类型?

1 个答案:

答案 0 :(得分:2)

模板函数对其模板参数强加隐式接口。如果您的类型operator+=没有T,那么您将收到编译错误。

#include <cstddef>
#include <vector>
using namespace std;

template <typename T>
T accumulate_sum (const std::vector<T>& v) {
    // check for type and decide whether to sum or return nothing

    T sum = v[0];
    for (size_t i = 1; i < v.size(); ++i) sum += v[i];
    return sum;
} 

struct Test {}; // not additive

int main()
{
    std::vector<Test> v { Test{}, Test{} };
    accumulate_sum(v);
}

这将显示以下错误消息(Live Example

main.cpp:10:47: error: no viable overloaded '+='
    for (size_t i = 1; i < v.size(); ++i) sum += v[i];
                                          ~~~ ^  ~~~~
main.cpp:19:5: note: in instantiation of function template specialization 'accumulate_sum<Test>' requested here
    accumulate_sum(v);
    ^

1 error generated.

使用概念技术规范,您可以添加语法约束并获得更好的错误消息。您也可以使用static_assert执行此操作。

#include <experimental/type_traits>
#include <utility>

template<class T>
using add_inc_t = decltype(std::declval<T&>() += std::declval<T>());

template<class T>
constexpr auto is_additive_v = std::experimental::is_detected_v<add_inc_t, T>;

template <typename T>
T accumulate_sum (const std::vector<T>& v) {
    static_assert(is_additive_v<T>, "the type T needs to be additive by providing operator+");

    // as before
}

Live Example使用gcc 6.0 SVN trunk(尚未发布)。