问题描述
我的目标是定义一个Recursive
类,该类以int N
为模板,以及一个或多个类型T,...Ts
,其行为应类似于std::pair
,
在尝试根据上述要求写下该类时,我想出了这个无效的代码(在这里,我还定义了一些必要的,因为它们有很大帮助,它们是{{1 }}),而且我不知道是否对我上面描述的内容进行了错误的设计(或者它是格式不正确的描述!),或者是否滥用了语言语法。
Ts...
我将添加到目前为止已完成的一些故障排除。在下文中,模板指定似乎可以正常工作。
Recursive
解决方法
您的错误是,首先,您声明Recursive
接收至少一个整数和两个类型,然后,您声明了部分特殊化,接收一个整数以及一种类型。
错误,因为在声明主模板接收两种或多种类型时,专业化不能仅接收一种类型。
可能违反直觉,但可以声明解决方案Recursive
仅接收一个一种类型(或更多)(这成为递归的基础),而特殊化则接收两种类型或更多
template <int N,typename T1,typename...>
struct Recursive : std::array<T1,N>
{ };
template <int N,typename T2,typename ...Ts>
struct Recursive<N,T1,T2,Ts...>
: std::pair<std::array<T1,N>,boost::hana::optional<std::vector<Recursive<N,Ts...>>>>
{ };
以下内容几乎没有修改(对于大小,用std::size_t
代替了int
;用std::optional
代替了boost::hana::optional
),但是完全编译了示例
#include <array>
#include <optional>
#include <string>
#include <utility>
#include <vector>
template <std::size_t N,N>
{ };
template <std::size_t N,std::optional<std::vector<Recursive<N,Ts...>>>>
{ };
template<typename ...T>
using Recursive2 = Recursive<2u,T...>;
template<typename ...T>
using Recursive3 = Recursive<3u,T...>;
int main ()
{
Recursive2<int> x{std::array<int,2u>{0,0}};
Recursive3<int,long> y{{std::array<int,3u>{0,0},{}}};
}
,
您有几个问题:
-
您的专业与您的主要模板不匹配
template <int N,typename ...Ts> struct Recursive;
至少需要3个参数。我认为应该是专业化的,主要模板应该是:template <int N,typename ...Ts> struct Recursive;
-
template <int N,typename T> struct Recursive<N,T>
的行为不像std::pair
(在您声明要求时,否则用法是错误的),您可能想要以下内容:template <int N,typename T> struct Recursive<N,T> : std::pair<std::array<T,decltype(boost::hana::nothing)>
-
您需要“转发”基类的构造函数,(也可以选择使用合成代替继承,或者使用特质来定义要使用的类型)或更改构造对象的方式。
结果是:
template <int N,typename ...Ts>
struct Recursive;
template <int N,Ts...>
: std::pair<std::array<T1,Ts...>>>
>
{
using std::pair<
std::array<T1,Ts...>>>>::pair;
};
template <int N,T>
: std::pair<std::array<T,decltype(boost::hana::nothing)>
{
using std::pair<std::array<T,decltype(boost::hana::nothing)>::pair;
};
template<typename ...T>
using Recursive2 = Recursive<2u,T...>;
int main() {
using boost::hana::nothing;
Recursive2<int> x(std::make_pair(std::array<int,2>{0,nothing));
}
,
我添加了自己的答案,因为我确实找到了解决方案(虽然在收到两个答案之前有点;但是使用std::optional
是我后来对其中一个答案做出的较晚更改)。但是,在我的解决方案中,我必须声明和定义通用模板和专用模板的构造函数,这使我认为它不如其他答案那么好。但是为什么不发布呢?
#include <cassert>
#include <iostream>
#include <array>
#include <optional>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
template <int N,typename T,typename ...Ts>
struct Recursive : std::pair<std::array<T,Ts...>>>
> {
template<typename ...Args>
Recursive(Args&& ...args) : std::pair<std::array<T,Ts...>>>
>(args...) {}
};
template <int N,T> : std::array<T,N> {
template<typename ...Args>
Recursive(Args&& ...x) : std::array<T,N>(x...) {}
};
template<typename ...T>
using Recursive2 = Recursive<2u,T...>;
int main() {
std::array<std::string,2> twoStrings{"hello","Hello"};
std::array<char,2> twoChars{'h','H'};
Recursive2<std::string> s{twoStrings};
assert(s == twoStrings);
std::vector<Recursive2<char>> vecOfTwoChars{twoChars,twoChars,twoChars};
Recursive2<std::string,char> sc{twoStrings,vecOfTwoChars};
assert(sc.first == twoStrings);
assert(sc.second->size() == 3);
assert(sc.second == vecOfTwoChars);
assert(sc.second.value()[0] == twoChars);
}