初步信息
我正在实现一个队列。我有一个Vec
类,看起来像这样:
#include <cstddef>
#include <span>
template<typename T, size_t Extent, bool Dynamic = (Extent == std::dynamic_extent)>
class Vec {
public:
constexpr size_t capacity(void) const;
~Vec();
};
template<typename T, size_t Extent>
class Vec<T, Extent, true> {
// Dynamic version
public:
Vec(size_t capacity);
};
template<typename T, size_t Extent>
class Vec<T, Extent, false> {
// Statically-sized version of the class
public:
constexpr Vec() = default;
};
字符串
也就是说,当Extent!= std::dyanmic_extent时,可以用constexpr Vec()
构造Vec
。否则,必须传入一个大小,构造函数为Vec(size_t capacity)
。这与std::span提供的API类似。
提问
我如何在一个新的类Queue
中包含它,这样我就可以在两个类之间共享大部分功能,但仍然有专门的ctors。例如,我想这样写:
template<typename T, size_t Extent = std::dynamic_extent>
class Queue {
public:
template</* only enable if Extent != std::dynamic_extent */>
constexpr Queue() {}
template</* only enable if Extent == std::dynamic_extent */>
Queue(size_t size) : m_slots(size) {}
// Other methods...
private:
Vec<T, Extent> m_slots;
// Other fields ...
};
型
我知道,我可以添加一个bool Dynamic
参数匹配Vec<T>
,但这样我就需要重复每个类中的所有字段,并提供重复的函数定义。
我尝试了几种不同的模板表达式变体(只显示了constexpr Queue()
的模板,Queue(size_t size)
的表达式只是明显的逆)。
尝试1:未命名,默认参数,可选无效
template<typename = typename std::enable_if_t<Extent != std::dynamic_extent>>
constexpr Queue() {}
型
尝试2:尝试模拟the c++ docs on std::enable_if
template<std::enable_if_t<Extent != std::dynamic_extent, bool> = true>
型
这两次尝试都失败了,并出现了警告:
/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/type_traits:2608:44: error: no type named 'type' in 'std::enable_if<false, bool>'; 'enable_if' cannot be used to disable this declaration
2608 | using enable_if_t = typename enable_if<_Cond, _Tp>::type;
| ^~~~~
../src/queues/spsc.hh:34:16: note: in instantiation of template type alias 'enable_if_t' requested here
34 | template<std::enable_if_t<Extent == std::dynamic_extent, bool> = true>
|
型
我如何实现这种行为?是否有我没有看到的更好的模式?
链接
我在this godbolt中复制了这个问题,我的两次尝试。
1条答案
按热度按时间yqyhoc1h1#
如果你看一下cppreference的
std::span
's constructor文档,你会看到它是如何在C++20中使用std::dynamic_extent
来限制它的一些构造函数的。顺便说一句,它根本没有在模板参数中使用SFINAE,而是使用了新的explicit(expression)
特性,例如:字符串