c++ - 区分添加剂类型?

标签 c++ templates

我在泛型编程方面的第一步包括编写一个简单的函数,该函数累加作为其参数传递的 vector 的总和。要注意的是,该函数应该仅适用于具有合计有意义的值的类型。

代码很简单:

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

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

最佳答案

模板函数在其模板参数上强加了一个隐式接口(interface)。如果您的类型 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);
}

这将给出以下错误信息 (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 主干(尚未发布)。

关于c++ - 区分添加剂类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34918190/

相关文章:

c++ - SFML:对 _imp_ 的 undefined reference

c++ - 模板化函数模板特化

python - 在 Django 中显示数据

c++ - 这段代码做了什么,为什么编译?

c++ - 如果模板参数也提供比较运算符,则有条件地提供比较运算符的重载

c++ - 堆腐败?在我的动态内存中?

c++ - 如何确定宽字符串文字的字节顺序?

c++ - 将指针传递给指向函数的指针

C++,多次重复一个函数的输入

C++ libPNG - 简单的初始化错误