是否可以引用模板模板参数?

问题描述 投票:0回答:1

我正在通过实现线性代数库来试验 C++ 中的模板,因此这个示例可能不是最适合这项工作。

假设我有一个 N 维容器,其中包含我想要继承的数据和向量和矩阵的常用函数(我知道,定义 Matrix 类型然后使用

using
声明是一种常见的做法不同的线性代数类型,就像它们在 eigen 中所做的那样,但我想继承这个容器,然后向各种类型添加方法,同样,它可能不是最合适的,但它是一个实验)。

template <typename T, std::size_t... Dims>
class NDimContainer {
public:
    auto operator+=(const NDimContainer &other) {
        std::transform(elems.begin(), elems.end(), other.begin(), std::plus<T>());
        return *this;
    }
private:
    std::array<T, (... * Dims)> elems;
};

template <typename T, std::size_t Dims>
class Vector : public NDimContainer<T, Dims> { ... }

问题是:是否可以像这样访问模板中指定的模板参数

N
Dims...

template <template<typename N, std::size_t... Dims> typename T>
require std::is_derived_from<NDimContainer<N, Dims...>, T<N, Dims...>>
auto operator+(const T &lhs, const T& rhs) { 
    return T { lhs } += rhs;
}

我知道可以这样做:

template <template<typename, std::size_t...> typename T, typename N, std::size_t... Dims>
require std::is_derived_from<NDimContainer<N, Dims...>, T<N, Dims...>>
auto operator+(const T &lhs, const T& rhs) { ... }

但是模板将无法匹配,例如

Vector
类型(或者至少在我的情况下没有,如果是一些微不足道的错误,请纠正我)。

有什么方法可以让这项工作顺利进行,以便我可以做这样的事情吗?

Vector<int, 3> a = Vector<int, 3>() + Vector<int, 3>();

我在此处此处找到了有关此主题的先前问题。但这些都不能真正解决我的用例。

禁止更简单的解决方案的罪魁祸首是

Dims...
,因为我不知道如何做这样的事情:

template <typename T, std::size_t... Dims>
class A {
public:
    using Type = T;
    using Dimensions = Dims...; // Error
};

可能可以使用

std::integer_sequence
,但这会带来额外的空间成本,我不想付费。

我尝试过这样的事情:

template <template<typename N, std::size_t... Dims> typename T, typename NN = N, std::size_t... DDims = Dims>
require std::is_derived_from<NDimContainer<N, Dims...>, T<N, Dims...>>
auto operator+(const T &lhs, const T& rhs) { ... }

但这显然也行不通。

是否可以进行类似的构造?

编辑:添加最小的可重现示例

#include <array>

template<typename T, std::size_t ... Dims>
struct A {
    std::array<T,(Dims*...)> data = {};
    A& operator+=( const A& ) noexcept;
};

// This works, but only for because of the conversion that is defined in Vector type
template<typename T, std::size_t... Dims>
auto operator+( const A<T,Dims...>& lhs, const A<T,Dims...>& rhs) -> A<T,Dims...> {
    return A{lhs} += rhs;
}

// This is the one I would like it matched instead, because then it would be instantiated for
// particular type.
template<template<typename TT, std::size_t ... DD> typename T1, typename T, std::size_t... Dims>
auto operator+( const A<T,Dims...>& lhs, const A<T,Dims...>& rhs) -> A<T,Dims...> {
    return A{lhs} += rhs;
}

template<typename T, std::size_t N>
struct Vector : A<T,N> {
    using Base = A<T,N>;

    Vector() = default;
    Vector(const Base& base) : Base(base) {}
};

using Vector3d = Vector<double,3>;

int main() {
    Vector3d vec = Vector3d{} + Vector3d{};

    return 0;
}
c++ templates variadic-templates
1个回答
0
投票

您的问题太长,里面的问题太多。我会重点关注这个:

问题是:是否可以访问模板中指定的模板参数 N 和 Dims...,如下所示:

template <template<typename N, std::size_t... Dims> typename T>
require std::is_derived_from<NDimContainer<N, Dims...>, T<N, Dims...>>
auto operator+(const T &lhs, const T& rhs) { 
    return T { lhs } += rhs;
}

不。这里

template <template<typename N, std::size_t... Dims> typename T>
你说的是
T
是一个带有参数
N
Dims...
的模板。您可以实例化
T
,但无法从
T
推导出
N
Dims...
的值,因为它们是参数。

您所问的内容类似于:“给定一个以

f
作为参数的函数
int x
,我能找出
x
的值是多少吗?”。当然不是。
f
是一个可以传递任何
x
的函数。

我感觉模板模板参数的使用毫无意义,就像我以前见过的那样。我想你实际上想要这样的东西:

 template <typename T>
 require std::is_derived_from<NDimContainer<T>>
 auto operator+(const T &lhs, const T& rhs) { 
     return T { lhs } += rhs;
 }

其中

T
是具有参数
N
Dims..
的某个模板的实例。如果是这种情况,那么您可以从该实例化
T
(一种类型)、参数
N
Dim...
中推断出
T
与某些
U<N,Dims...>
的类型相同。这是可能的,但这是一个不同的问题。

© www.soinside.com 2019 - 2024. All rights reserved.