模板元编程是一种元编程技术,其中编译器使用模板生成临时源代码,该代码由编译器与其余源代码合并然后编译。
让我们考虑以下情况,我正在编写库,而不是带有成本的运行时多态性,但与所有声明都有清晰可见的接口,我选择通用程序...
我正在尝试模拟std::any,我的想法是使用基类指针指向不同类型的模板派生类,来实现存储不同类型数据的功能,比如...
如何定义一个 C++ 概念来检查给定的模板类型参数是否是pair的顺序容器<T, T>
如何定义 C++ 概念来检查给定模板类型参数是否是顺序容器或成对范围(例如向量>. 让我们说出
我有一个模板类,它使用模板参数(std::enable_if_t)来限制主模板参数,如下所示: 模板 我有一个模板类,它使用模板参数(std::enable_if_t)来限制主模板参数,如下所示: template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> class Foo { void foo(); } template<typename T> void Foo<T>::foo() {} // compiler complains 我知道我可以使用 static_assert 解决这个问题,但我想知道在这种情况下正确的方法是什么。 我想我可以简单地再次复制两个模板参数,但这对我来说似乎很奇怪。 您必须添加第二个模板参数: // ..................vvvvvvvvvv template<typename T, typename U> void Foo<T, U>::foo() {} // compiler doesn't complains anymore // ........^^ 或者,也许更好,在类中实现该方法: template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> class Foo { void foo() {} // .......^^^ }; 无论如何...考虑到您使用 SFINAE 限制(第一个)参数类型的方法有一个缺陷:您正在对第二个模板参数的 default 值进行操作,因此可以通过显式绕过它在实例化中包括第二个模板参数。 我的意思是...当 T 是算术时,您可以正确定义类型: Foo<int> f; // compile 并且当 T 不是算术时正确地无法编译: Foo<void> f; // compilation error 但是,当您显式包含第二个模板参数时,它会编译(当 T 不是算术时): Foo<void, void> f; // compiles!!! 我想你不会 Foo<void, void> 进行编译。 为了避免这个问题,可以在等号左边使用SFINAE,删除模板参数,而不是默认值。 例如,你可以写: template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, bool> = true> class Foo { void foo() {} }; 这样,当第一个模板参数不是算术类型时,您可以确定没有人可以实例化 Foo 对象。 这个解决方案有一个小问题(或者可能没有……取决于您的期望):您可以通过同一个 T 参数定义两个不同的类。 我的意思是...你可以定义: Foo<int> f0; Foo<int, true> f1; // same type as f0 Foo<int, false> f2; // different type from f0 and f1 为了避免这种情况,对于第二个参数的类型,可以使用接受单个值的类型。例如:std::nullptr_t template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, std::nullptr_t> = nullptr> class Foo { void foo() {} }; 现在,您可以拥有一个 Foo<int>,它是 Foo<int, nullptr> 的简写,但不是第二个模板参数不同的类。 您可以在类中将 SFINAE 设为嵌套模板,以限制函数的类型。 SFINAE 作为嵌套模板: // class declaration template <typename T> class Foo; // class definition template <typename T> class Foo { void foo(); template <typename U, typename = std::enable_if_t<std::is_arithmetic_v<U> > > void somefunction(U val); // function declaration } // somefunction definition template <typename T> template <typename U, typename> void Foo<T>::somefunction(U val) {// *** code here *** //;} 我通常使用这种语法,因为编译时错误消息至少在某种程度上是可读的: msvc:main.cpp(21,22): error C2079: 's' uses undefined class 'Foo<std::string,void>' 海湾合作委员会:main.cpp:21:22: error: aggregate ‘Foo > s’ has incomplete type and cannot be defined #include <type_traits> #include <iostream> #include <string> template <typename type_t, typename enable_t = void> class Foo; template <typename type_t> class Foo<type_t, std::enable_if_t<std::is_arithmetic_v<type_t>>> { public: void foo() { std::cout << "foo\n"; } }; int main() { Foo<int> f; Foo<std::string> s; f.foo(); return 0; }
我想编写一个函数,将 lambda 分派到外部库函数模板(如果库中存在此函数模板)或直接执行 lambda。 我们可以...
我有这门课 模板 结构体ArrayPrimitive { constexpr ArrayPrimitive(const ValueType (&array)[Size]) { std::copy(数组,数组+大小,d...
我有这门课 模板 结构体ArrayPrimitive { constexpr ArrayPrimitive(const ValueType (&array)[Size]) { std::copy(数组,数组+大小,d...
我想编写这段代码,但它会产生错误。 模板 结构体A { 结构体 B { }; B f() { 返回 B{}; } }; 模板 constexpr bool val = fals...
我正在尝试模板化一些转换运算符函数来接受各种算术类型,即有符号/无符号整数/浮点类型,因此有4种不同的函数模板
我试图弄清楚如何使用折叠表达式(或其他元编程技术)来摆脱下面代码片段中的“if else”分支。 模板 是...
我正在尝试创建一个模板类,它将从给定类型的文件中读取数据到 std::variant 向量中。 ...
如何将变量名作为字符串传递给函数? (Clojure 脚本)
情况描述 我想为某个元素制作一个表单模板,但它们必须动态创建。组件中涉及的元数据应该使用传递的变量名称...
我正在关注如何在 C++ 中实现常量表达式计数器教程,并尝试修复没有宏、标记或外部工具的 C++14 反射谈话限制。 基本...
C++元编程中从类型列表中删除类型是什么意思。任何人都可以提出任何简单的例子吗? 类 null_typelist {}; 模板 结构
使用 CRTP(奇怪的重复模板模式),您可以提供一个具有派生类知识的基类。创建一个存储每个类的实例的数组并不难...
你好:) 我正在使用 C++ 模板元编程实现编译时拓扑排序算法。该算法旨在对游戏中不同系统之间的依赖关系图进行排序
我想要一个能够存储接受“N”个双参数的函数对象的模板类。该伪代码使用不存在的 std::repeated_type 模板函数...
我想知道是否有技巧可以简化 trait 的编写以返回类型是否为 noexcept 函数。目前我的实现如下,它只列出了所有...
我正在尝试使用 TMP 实现列表及其操作。 以下代码无法编译,Insert_t 无法实例化(最后一行): #包括 模板 我正在尝试使用 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...>> 不明确。我不明白为什么,因为第一个部分专业化应该是模式限制的,以及如何解决这个问题。
习惯用x宏来生成强大的代码。我特别喜欢的功能之一是我不能弄乱值的顺序,也不能忘记一个。 我想知道有没有