我正在尝试使用 TMP 实现列表及其操作。
以下代码编译不通过,
Insert_t
实例化失败(最后一行):
#include <type_traits>
template <int... I>
struct List;
template <int Em, typename TList>
struct Append;
template <int Em, typename TList>
using Append_t = typename Append<Em, TList>::type;
template <int Em, int... I>
struct Append<Em, List<I...>> {
using type = List<Em, I...>;
};
template <int Em, int Idx, typename TList>
struct Insert;
template <int Em, int Idx, typename TList>
using Insert_t = typename Insert<Em, Idx, TList>::type;
template <int Em, int... I>
struct Insert<Em, 0, List<I...>> : Append<Em, List<I...>> {};
template <int Em, int Idx, int H, int... I>
struct Insert<Em, Idx, List<H, I...>> : Append<H, Insert_t<Em, Idx-1, List<I...>>> {};
static_assert(std::is_same_v<Insert_t<4, 4, List<0, 1, 2, 3>>, List<0, 1, 2, 3, 4>>); // OK
static_assert(std::is_same_v<Insert_t<-1, 3, List<6, 3, 1, 4>>, List<6, 3, 1, -1, 4>>); // Fails
g++ 编译器给出以下错误,clang 提供相同的错误。我不明白为什么实例化不明确,因为我提供了索引为 0 的专业化:
main.cpp: In instantiation of ‘struct Insert<-1, 1, List<1, 4> >’:
main.cpp:27:8: recursively required from ‘struct Insert<-1, 2, List<3, 1, 4> >’
main.cpp:27:8: required from ‘struct Insert<-1, 3, List<6, 3, 1, 4> >’
main.cpp:21:7: required by substitution of ‘template<int Em, int Idx, class TList> using Insert_t = typename Insert::type [with int Em = -1; int Idx = 3; TList = List<6, 3, 1, 4>]’
main.cpp:30:61: required from here
main.cpp:27:8: error: ambiguous template instantiation for ‘struct Insert<-1, 0, List<4> >’
27 | struct Insert<Em, Idx, List<H, I...>> : Append<H, Insert_t<Em, Idx-1, List<I...>>> {};
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:24:8: note: candidates are: ‘template<int Em, int ...I> struct Insert<Em, 0, List<I ...> > [with int Em = -1; int ...I = {4}]’
24 | struct Insert<Em, 0, List<I...>> : Append<Em, List<I...>> {};
| ^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:27:8: note: ‘template<int Em, int Idx, int H, int ...I> struct Insert<Em, Idx, List<H, I ...> > [with int Em = -1; int Idx = 0; int H = 4; int ...I = {}]’
27 | struct Insert<Em, Idx, List<H, I...>> : Append<H, Insert_t<Em, Idx-1, List<I...>>> {};
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:27:8: error: invalid use of incomplete type ‘struct Insert<-1, 0, List<4> >’
main.cpp:18:8: note: declaration of ‘struct Insert<-1, 0, List<4> >’
18 | struct Insert;
| ^~~~~~
main.cpp: In instantiation of ‘struct Insert<-1, 2, List<3, 1, 4> >’:
main.cpp:27:8: required from ‘struct Insert<-1, 3, List<6, 3, 1, 4> >’
main.cpp:21:7: required by substitution of ‘template<int Em, int Idx, class TList> using Insert_t = typename Insert::type [with int Em = -1; int Idx = 3; TList = List<6, 3, 1, 4>]’
main.cpp:30:61: required from here
main.cpp:27:8: error: no type named ‘type’ in ‘struct Insert<-1, 1, List<1, 4> >’
27 | struct Insert<Em, Idx, List<H, I...>> : Append<H, Insert_t<Em, Idx-1, List<I...>>> {};
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp: In instantiation of ‘struct Insert<-1, 3, List<6, 3, 1, 4> >’:
main.cpp:21:7: required by substitution of ‘template<int Em, int Idx, class TList> using Insert_t = typename Insert::type [with int Em = -1; int Idx = 3; TList = List<6, 3, 1, 4>]’
main.cpp:30:61: required from here
main.cpp:27:8: error: no type named ‘type’ in ‘struct Insert<-1, 2, List<3, 1, 4> >’
main.cpp: In substitution of ‘template<int Em, int Idx, class TList> using Insert_t = typename Insert::type [with int Em = -1; int Idx = 3; TList = List<6, 3, 1, 4>]’:
main.cpp:30:61: required from here
main.cpp:21:7: error: no type named ‘type’ in ‘struct Insert<-1, 3, List<6, 3, 1, 4> >’
21 | using Insert_t = typename Insert<Em, Idx, TList>::type;
| ^~~~~~~~
main.cpp:30:20: error: template argument 1 is invalid
30 | static_assert(std::is_same_v<Insert_t<-1, 3, List<6, 3, 1, 4>>, List<6, 3, 1, -1, 4>>);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我想实现一个 Insert 操作以在列表 TList 中的位置 Idx 插入一个新元素 Em。在我的实现中,我为
Insert<Em, 0, List<I...>>
提供了一个模板部分特化,以便结构中提供的类型与 Append<Em, TList>
相同。但是,它被认为与其他偏特化 Insert<Em, Idx, List<H, I...>>
不明确。我不明白为什么,因为第一个部分专业化应该是模式限制的,以及如何解决这个问题。