区分添加剂类型

Differentiating additive types?

本文关键字:类型 添加剂      更新时间:2023-10-16

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

代码很简单:

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;
} 

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

模板函数在其模板参数上强加一个隐式接口。如果您的类型 T 没有operator+=,则会收到编译器错误。

#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);
}

这将给出以下错误消息(实时示例

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
}

使用 gcc 6.0 SVN 主干的实时示例(尚未发布)。