Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ decltype不解析嵌套向量。如何使用嵌套向量的模板?_C++_Templates_Vector_Nested - Fatal编程技术网

C++ decltype不解析嵌套向量。如何使用嵌套向量的模板?

C++ decltype不解析嵌套向量。如何使用嵌套向量的模板?,c++,templates,vector,nested,C++,Templates,Vector,Nested,我试图重载+运算符来处理嵌套向量。我原以为该函数会调用自己,直到嵌套向量解析为基本类型,但在编译它时,我得到了一个巨大的错误列表。我定义的向量操作适用于基本类型,但不适用于数量可变的嵌套向量。唯一对嵌套向量有效的操作是您遇到的问题与名称查找有关。您正在operator+上执行非限定名称查找,如下所示: template<typename T1, typename T2> auto operator+(const std::vector<T1>& l, const

我试图重载+运算符来处理嵌套向量。我原以为该函数会调用自己,直到嵌套向量解析为基本类型,但在编译它时,我得到了一个巨大的错误列表。我定义的向量操作适用于基本类型,但不适用于数量可变的嵌套向量。唯一对嵌套向量有效的操作是您遇到的问题与名称查找有关。您正在
operator+
上执行非限定名称查找,如下所示:

template<typename T1, typename T2>
auto operator+(const std::vector<T1>& l, const std::vector<T2>& r) 
-> std::vector<decltype((l[0] + r[0]))> {
                        ^^^^^^^^^^^^^
如果没有C++14,您必须将所有内容转发到另一个函数,以便名称查找能够成功。你可以使用ADL技巧,但我认为模板更容易理解。这里有一个可行的解决方案:

template <typename T1, typename T2>
struct Add : std::plus<T1> { };

template <typename T1, typename T2>
struct Add<std::vector<T1>, std::vector<T2>>
{   
    auto operator()(const std::vector<T1>& l, const std::vector<T2>& r)
        -> std::vector<decltype(Add<T1,T2>{}(l[0], r[0]))>
    {
        using type = decltype(Add<T1,T2>{}(l[0], r[0]));
        std::vector<type> ans;

        if(l.size() == std::max(l.size(),r.size()))
            std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans), Add<T1,T2>{});
        else
            std::transform(l.begin(), l.end(), r.begin(), std::back_inserter(ans), Add<T1,T2>{});
        return ans;
    };
};

template <typename T1, typename T2>
auto operator+(const std::vector<T1>& lhs, const std::vector<T2>& rhs)
    -> decltype(Add<std::vector<T1>, std::vector<T2>>{}(lhs, rhs))
{
    return Add<std::vector<T1>, std::vector<T2>>{}(lhs, rhs);
}
模板
struct Add:std::plus{};
模板
结构添加
{   
自动运算符()(常数std::vector&l,常数std::vector&r)
->向量
{
使用type=decltype(Add{}(l[0],r[0]);
std::向量ans;
如果(l.size()==std::max(l.size(),r.size())
std::transform(r.begin()、r.end()、l.begin()、std::back_uinserter(ans),Add{});
其他的
std::transform(l.begin()、l.end()、r.begin()、std::back_inserter(ans)、Add{});
返回ans;
};
};
模板
自动运算符+(常量标准::向量和左行,常量标准::向量和右行)
->decltype(添加{}(lhs,rhs))
{
返回Add{}(lhs,rhs);
}

您遇到的问题与名称查找有关。您正在
operator+
上执行非限定名称查找,如下所示:

template<typename T1, typename T2>
auto operator+(const std::vector<T1>& l, const std::vector<T2>& r) 
-> std::vector<decltype((l[0] + r[0]))> {
                        ^^^^^^^^^^^^^
如果没有C++14,您必须将所有内容转发到另一个函数,以便名称查找能够成功。你可以使用ADL技巧,但我认为模板更容易理解。这里有一个可行的解决方案:

template <typename T1, typename T2>
struct Add : std::plus<T1> { };

template <typename T1, typename T2>
struct Add<std::vector<T1>, std::vector<T2>>
{   
    auto operator()(const std::vector<T1>& l, const std::vector<T2>& r)
        -> std::vector<decltype(Add<T1,T2>{}(l[0], r[0]))>
    {
        using type = decltype(Add<T1,T2>{}(l[0], r[0]));
        std::vector<type> ans;

        if(l.size() == std::max(l.size(),r.size()))
            std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans), Add<T1,T2>{});
        else
            std::transform(l.begin(), l.end(), r.begin(), std::back_inserter(ans), Add<T1,T2>{});
        return ans;
    };
};

template <typename T1, typename T2>
auto operator+(const std::vector<T1>& lhs, const std::vector<T2>& rhs)
    -> decltype(Add<std::vector<T1>, std::vector<T2>>{}(lhs, rhs))
{
    return Add<std::vector<T1>, std::vector<T2>>{}(lhs, rhs);
}
模板
struct Add:std::plus{};
模板
结构添加
{   
自动运算符()(常数std::vector&l,常数std::vector&r)
->向量
{
使用type=decltype(Add{}(l[0],r[0]);
std::向量ans;
如果(l.size()==std::max(l.size(),r.size())
std::transform(r.begin()、r.end()、l.begin()、std::back_inserter(ans)、Add{});
其他的
std::transform(l.begin()、l.end()、r.begin()、std::back_inserter(ans)、Add{});
返回ans;
};
};
模板
自动运算符+(常量标准::向量和左行,常量标准::向量和右行)
->decltype(添加{}(lhs,rhs))
{
返回Add{}(lhs,rhs);
}
My on在此解释了您的方法失败的原因以及解决方案的一种可能方法。我只是想到了一个非常简单的方法,我觉得值得分享

问题是不能使用尾随返回类型,因为函数名本身还不在范围内,所以不能以这种方式使用递归。但是,没有什么可以阻止您编写一个元函数来确定返回类型应该是什么。这个元功能非常简单:

template <typename T1, typename T2>
struct nested_common_type :std::common_type<T1, T2> { };

template <typename T1, typename T2>
struct nested_common_type<std::vector<T1>, std::vector<T2>> {
    using type = std::vector<typename nested_common_type<T1,T2>::type>;
};

template <typename T1, typename T2>
using vector_common_type_t = std::vector<typename nested_common_type<T1,T2>::type>;
我在这里解释了您的方法失败的原因以及解决方案的一种可能方法。我只是想到了一个非常简单的方法,我觉得值得分享

问题是不能使用尾随返回类型,因为函数名本身还不在范围内,所以不能以这种方式使用递归。但是,没有什么可以阻止您编写一个元函数来确定返回类型应该是什么。这个元功能非常简单:

template <typename T1, typename T2>
struct nested_common_type :std::common_type<T1, T2> { };

template <typename T1, typename T2>
struct nested_common_type<std::vector<T1>, std::vector<T2>> {
    using type = std::vector<typename nested_common_type<T1,T2>::type>;
};

template <typename T1, typename T2>
using vector_common_type_t = std::vector<typename nested_common_type<T1,T2>::type>;


我认为您无法根据函数本身定义
运算符+
函数的返回类型。返回类型应仅为
std::vector
std::vector
,否?请避免std容器的非特定运算符重载(您会遇到麻烦)在该链接的第三个答案的最后()他找到了一个嵌套向量的解决方案,然而,我想要n个嵌套向量。该线程中接受的答案看起来与您试图做的一样,除非我误解了您的问题。您所说的“非特定”运算符重载是什么意思?我认为您无法从函数本身定义
运算符+
函数的返回类型。返回类型应仅为
std::vector
std::vector
,否?请避免std容器的非特定运算符重载(您会遇到麻烦)在该链接的第三个答案的最后()他找到了一个嵌套向量的解决方案,然而,我想要n个嵌套向量。该线程中被接受的答案看起来与您试图做的一样,除非我误解了您的问题。您所说的“非特定”运算符重载是什么意思?将其包装在
命名空间std{}
中是最简单的。虽然这并不总是好的做法感谢所有有见地的评论和回答。@xcvr:更具体地说,这(通常)是标准完全禁止的。;-]@MattMcNabb:这不是专门化标准类模板,而是重载只涉及标准类型的自由运算符–AFAIK这是绝对不允许的。@MattMcNabb:它在
[namespace.std]
中(§17.6.4.2.1 in C++14)。措辞并不像我记得的那样具体,但至少它说:“C++程序的行为如果在名称空间<代码> STD<代码>中添加声明或定义,或者在命名空间>代码> STD < /C>中的命名空间是未定义的,除非另有说明。虽然这并不总是好的做法感谢所有有见地的评论和回答。@xcvr:更具体地说,这(通常)是标准完全禁止的。;-]@MattMcNabb:这不是专门化标准类模板,而是重载只涉及标准类型的自由运算符–AFAIK这是绝对不允许的。@MattMcNabb:它在
[namespace.std]
中(§17.6.4.2.1 in C++14)。措辞并不像我记忆中的那样具体,但至少它说:“C++程序的行为是und。
template <typename T1, typename T2>
struct nested_common_type :std::common_type<T1, T2> { };

template <typename T1, typename T2>
struct nested_common_type<std::vector<T1>, std::vector<T2>> {
    using type = std::vector<typename nested_common_type<T1,T2>::type>;
};

template <typename T1, typename T2>
using vector_common_type_t = std::vector<typename nested_common_type<T1,T2>::type>;
template <typename T1, typename T2,
          typename R = vector_common_type_t<T1,T2>>
R operator+(const std::vector<T1>& l, const std::vector<T2>& r)
{
    R ans;
    std::transform(l.begin(),
                   l.begin() + std::min(l.size(), r.size()),
                   r.begin(),
                   std::back_inserter(ans),
                   [](const T1& lhs, const T2& rhs){ return lhs + rhs; });
    return ans;
}