繁体   English   中英

带有可变参数包的模板化可添加 class

[英]templated addable class with variadic pack

再会,

我尝试实现一个 class ,它可以使用内部存储变量_val总结所有内容,见下文:

#include <utility>
#include <vector>
#include <cassert>

template <typename T>
class Addable {
    T _val;

  public:
    explicit Addable(T v) :_val(std::move(v)) {}

    template <typename ...Us>
    [[nodiscard]] constexpr T add(Us&& ...us) const
    {
        return (_val + ... + us);
    }

    template<typename U>
    [[nodiscard]] constexpr T add(U u) const
    {
        if constexpr (std::is_same_v<T, std::vector<U>>) {
            auto copy = _val;
            for (auto& n : copy) {
                n += u;
            }
            return copy;
        }
        else {
            return _val + u;
        }
    }
};


int main()
{
    using namespace std;

    assert(Addable<int>{42}.add() == 42);
    assert(Addable<int>{42}.add(1) == 43);
    assert(Addable<int>{42}.add(1, 1) == 44);
    assert(Addable<int>{2}.add(1, 1, 1, 1, 1) == 7);

    {
        vector v {2, 3};
        vector expected {3, 4};
        assert(Addable<vector<int>>{v}.add(1) == expected);
    }

    {
        vector v {2, 3};
        vector expected {5, 6};
//        assert(Addable<vector<int>>{v}.add(1, 2) == expected); // compile error...
    }

    return 0;
}

Class 工作 - 在这里使用带有简单T折叠表达式int - 像std::vector这样的T但仅适用于一个U u

当我尝试 append 为每个向量元素一个来自可变参数包的每个元素时,我做错了什么?...

这个重载处理所有的测试用例:

template <typename ...Us>
[[nodiscard]] constexpr T add(Us&& ...us) const
{
    if constexpr (!sizeof...(us))
    {
        return _val;
    }
    else if constexpr (std::is_same_v<T, std::vector< std::common_type_t<Us...> > > )
    {  // [2]
        auto copy = _val;
        for (int& i : copy)
            i += (us + ...);
        return copy;
    }
    else
    {
        return (_val + ... + us);
    }
}

在为T = vector调用的 [2] 块中,您需要遍历副本中的所有项目,并且对于每个项目,您必须从输入 arguments 添加折叠结果(us +...)

现场演示

当我尝试 append 为每个矢量元素一个来自可变参数包的每个矢量元素时,我做错了什么?..

我不明白你到底想要什么......无论如何

Addable<vector<int>>{v}.add(1, 2)

你用两个arguments 调用add()

您有两个版本的add() :可变参数的版本和接收一个参数的版本。

所以,用两个arguments 调用它,只有可变参数匹配

template <typename ...Us>
[[nodiscard]] constexpr T add(Us&& ...us) const
{
    return (_val + ... + us);
}

但是_val +... + us中的运算符+未定义,其中_valstd::vector<int>us...值是int s。 所以错误。

例如,如果您使用单个参数调用add()

Addable<vector<int>>{v}.add(2)

代码编译(调用管理std::vector情况的add()版本)但显然,当您运行编译的程序时assert()失败。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM