具有 std::array 大小类型的派生模板类
Posted
技术标签:
【中文标题】具有 std::array 大小类型的派生模板类【英文标题】:Derived template class with std::array size type 【发布时间】:2021-08-25 07:10:46 【问题描述】:我正在使用C++17
并且有一个模板类,它对模板变量类型有限制。我想添加一个派生类,该类还接受std::array
参数并模板化数组的大小。
template <typename T,
typename U = std::enable_if<std::is_same_v<T, int> || std::is_same_v<T, bool>>>
class Base
public:
Base(T param1) : value(param1)
T value;
;
template <typename T,
typename U = std::enable_if<std::is_same_v<T, int> || std::is_same_v<T, bool>>,
typename N = unsigned int>
class Derived : public Base<T, U>
public:
Derived(T param1, std::array<std::pair<T, bool>, N>&& param2) :
Base(param1),
arr(std::move(param2))
std::array<std::pair<T, bool>, N> arr;
;
// We can use Base as such
Base<int> b 23 ;
// I want to use Derived in such a way
Derived<int, 2> d 0, 1, true, 2, false ;
但是,我在构建或创建派生类的实例时遇到了麻烦。任何帮助表示赞赏!
编辑: 在通过切换变量和取消模板化 N 提供的建议中添加。 这是一个 MRE https://godbolt.org/z/MGj5YdbxP 创建派生实例时出现新错误。
编辑2: 我知道 sfinae 并会解决这个问题。有没有办法让它为 r-val 参考工作,所以我可以移动第二个参数? https://godbolt.org/z/YxYssKPn3 假设我还支持将被销毁的 T 的大型 std::string 类型。
【问题讨论】:
请提供minimal reproducible example,包括完整的错误消息 也许交换U,N
的位置并制作N
std::size_t
而不是类型?这样来自Derived<int,2>
的两个被分配给U
而不是N
第二个参数用 && 没有多大意义(类型不会从移动中获得太多收益)。如果你通过了std::move(a)
。更通常的做法是通过值或const &
获取 Derived 构造函数的第二个参数。 godbolt.org/z/h8YsE8xsG
@alfC 如果我也支持 T 的 std::string 类型并且想要移动很快就会被破坏的很长的字符串怎么办。有没有办法让它为 r-val ref 工作?
问得好,我认为此举不会自动通过std::array
传递(也许是通过std::pair
)。我必须在实际代码中看到它。
【参考方案1】:
只需重新排序参数,并使用非类型模板参数:
template <typename T,
std::size_t N,
std::enable_if_t<std::is_same_v<T, int> || std::is_same_v<T, bool>, int> = 0>
class Derived : public Base<T>
// ...
;
注意:typename U = std::enable_if<condition>
不启用 SFINAE。
您需要typename U = std::enable_if_t<condition>
或typename U = typename std::enable_if<condition>::type
。
该表单可能被劫持(就像您使用Base<T, U>
一样);更喜欢std::enable_if_t<condition, int> = 0
。
【讨论】:
是的,我将使用 enable_if_t 并知道它是如何工作的,谢谢。这不是我在这个问题上遇到的问题。【参考方案2】:Derived(T param1, std::array<std::pair<T, bool>, N>&& param2)
此构造函数中用于std::array
的第二个模板参数N
在这里是一个类型(模板参数),而std::array
需要一个非类型模板的有效参数std::size_t
类型的参数。
您似乎想在 std::size_t
类型的非类型模板参数上参数化您的 Derived
类型。
【讨论】:
【参考方案3】:IIRC,我对您的代码进行了 2 处更改:
1.来自 Derived(T param1, std::array<std::pair<T, bool>, N>&& param2) : Base(param1),
给 Derived(T param1, std::array<std::pair<T, bool>, N>&& param2) : Base<T,U>(param1),
2.来自template <typename T, typename U = std::enable_if<std::is_same_v<T, int> || std::is_same_v<T, bool>>, typename N = unsigned int>
致template <unsigned int N ,typename T, typename U = std::enable_if<std::is_same_v<T, int> || std::is_same_v<T, bool>> >
代码如下:
#include<array>
#include<map>
template <typename T,
typename U = std::enable_if<std::is_same_v<T, int> || std::is_same_v<T, bool>>>
class Base
public:
Base(T param1) : value(param1)
T value;
;
template <unsigned int N
,typename T,
typename U = std::enable_if<std::is_same_v<T, int> || std::is_same_v<T, bool>>
>
class Derived : public Base<T, U>
public:
Derived(T param1, std::array<std::pair<T, bool>, N>&& param2) :
Base<T,U>(param1),
arr(std::move(param2))
std::array<std::pair<T, bool>, N> arr;
;
// We can use Base as such
Base<int> b 23 ;
int main()
// I want to use Derived in such a way
Derived<2, int> d 0, std::make_pair(1, true), 2, false ;
return 0;
【讨论】:
感谢您的回答!我喜欢你保留 r-val ref 的方式,但是有没有办法通过传入 std::array 而不是在d
中定义它来让它工作?
使用std::move
? ``` std::array<:pair bool>, 2> myarray;; myarray[0] = std::make_pair(1, true); myarray[1] = std::make_pair(2, false); // 我想以这样的方式使用 Derived Derived d( 0, std::move(myarray) ); ```
看来我可能不得不使用 std::move... 谢谢!以上是关于具有 std::array 大小类型的派生模板类的主要内容,如果未能解决你的问题,请参考以下文章
在 C++11 中具有对齐元素的 std::array 类型
为啥 std::array::size constexpr 具有简单类型(int,double,...)而不是 std::vector (GCC)?