可变参数模板是采用可变数量参数的模板。
理解 SFINAE:部分专门化类之外的成员函数声明以及可变参数类中的模板
我想做的事: 创建一个“指令集”对象 由别处的指针持有 保存可变数量的指令对象,其类型满足概念“is_instruction_type” 有'额外...
我有一个看起来像这样的函数 模板 std::tuple call_nn(std::string_view 查询,参数...参数) { pqxx::工作 w(con_); pqxx::ro...
我有一个函数 unpack,它应该从可变参数模板表达式构造一个 std::tuple。该函数如下所示(包括注释掉的失败尝试): 模板 我有一个函数 unpack,它应该从可变参数模板表达式构造一个 std::tuple。该函数如下所示(包括注释掉的失败尝试): template<typename T, typename... Ts> std::tuple<T,Ts...> unpack(std::stringstream& ss) { T t{}; WriteTypeStruct ret{}; if (writeType(ret, ss, t); (!ss || ret.err)) { throw std::runtime_error(ret.msg); } //std::tuple args = {extract<std::decay_t<Ts>>(ss)...}; //std::tuple args = unpack<typename std::decay_t<Ts>...>(ss); //return {t, unpack<Ts>(ss)...}; //return std::make_tuple(t, unpack<Ts>(ss)...); //std::tuple<Ts...> unpacked = {unpack<Ts>(ss)...}; //return std::make_tuple(t, unpacked); //return std::tuple_cat(std::tuple<T>(t), std::make_from_tuple(unpack<Ts>(ss)...)); return std::make_tuple(t, std::make_from_tuple<Ts...>(unpack<Ts>(ss)...)); // <-- cannot compile! } 函数 writeType 是一系列模板化重载函数,我用它来检查是否可以从 std::stringstream 中提取预期类型。该函数在 WriteTypeStruct 中放置一些返回值,其中包含一个布尔值和一个用于错误消息的字符串。 TLDR;我正在为命令控制台编写一个基于字符串的解释器。 问题的完整介绍如下:如何为基于文本的命令控制台存储参数化的强类型函数,特别是@jarod42的答案。我正在使用这个 unpack 函数而不是 extract。 关于如何展平std::tuple这里有一个很好的解释,但我希望通过首先不创建嵌套元组可以避免这种代码。 但我似乎无法弄清楚正确的语法。 我将从反序列化开始: template<class T> T deserialize(std::stringstream& ss) { T t{}; WriteTypeStruct ret{}; if (writeType(ret, ss, t); (!ss || ret.err)) { throw std::runtime_error(ret.msg); } return t; } 其语义非常简单。 template<class...Ts> std::tuple<Ts...> unpack(std::stringstream& ss) { return std::tuple<Ts...>{ unpack<Ts>(ss)... }; } 保证这些 {} 内的评估顺序。 (注意:这是因为我使用了 {} ctor,而不是函数调用。程序员可以轻松地对上面的内容进行更改,“不执行任何操作”,并以某种方式严重破坏它,具体取决于您使用的编译器。) 大多数 unpack 尝试遇到的问题是它们不能很好地处理 unpack<>(终止情况)。 那些调用 unpack<Ts>... 而不是 unpack<Ts...> 的(即,保证通过 1,并且解包调用在 0 处被消除)最终会导致 1 层过多的元组,unpack<Ts>... 是一组元组,您可以包裹在元组中。 return std::tuple_cat(std::tuple<T>(t), std::make_from_tuple(unpack<Ts>(ss)...)); 这已经很接近了。要修复它: return std::tuple_cat(std::tuple<T>(t), unpack<Ts>(ss)...); 只需去除 tuple 上多余的 unpack 层即可; unpack 已经返回一个元组。然后我们tuple_cat,它支持任意数量的元组。 我们可以尝试优化这个: return std::tuple_cat(std::tuple<T>(t), unpack<Ts...>(ss)); 但这会遇到空的unpack<>问题。 我遇到的一个问题是,您将所有内容放入一个元组中,只是为了再次将其取出。 空的unpack<>也可以处理。在 unpack 之前添加: template<bool empty_pack=true> std::tuple<> unpack(std::stringstream& ss) { return {}; } 那么 unpack<> 应该称之为重载。 但是,我发现所有这些都不如从元组版本调用的 1 元素版本优雅。 最后,我们可以编写一个元组展平函数,它接受任何一组参数,如果其中任何一个是元组,它就会展平它们,并返回融合列表。我个人认为这个函数很诱人,但不是一个好主意,因为它会立即“解决”问题,但随后会导致棘手的问题。 这有点像编写一个对文本进行取消转义的函数,但对任意数量的层进行取消转义,直到不再有转义序列为止。或者转义文本,但拒绝转义任何已经转义的内容。 您将其放入业务逻辑链中,它“解决”了不均匀转义或未转义数据的问题......并以无法修复的方式破坏事物。
我有一个模板化容器,将值存储在向量中。字符串或整数没有问题,但 size_t 值无法编译。编译器似乎假设我想用...初始化向量
我有一个模板化容器,将值存储在向量中。字符串或整数没有问题,但 size_t 值无法编译。编译器似乎假设我想用...初始化向量
以下内容按预期工作: 模板 auto countNumberOfTypes() { return sizeof...(类型); } 模板 consteval auto functionReturnsFunction() {
我有以下状态机示例,它使用枚举来专门化带有可变参数包的模板方法。当我通过
我正在尝试将可变参数模板函数应用于元组。我发现以下适用于 C++14 的解决方案(请参阅 https://stackoverflow.com/a/37100646/2712726)。 #包括 模板<
有人可以帮助我如何用可变参数模板参数替换模板类型列表,并在类中创建每种类型的唯一指针。 问题是我有课 模板...
仅进一步传递参数(不单独访问)时模板化和非模板化可变参数函数之间的编译差异
我试图了解 C++ 中模板化与非模板化可变参数函数在编译(特别是编译时间)方面的差异,在特殊情况下...
我正在尝试创建可变参数模板,它可以获取左值、右值和右值引用作为参数。但似乎 T&& 被视为右值引用并且不接受其他类型...
请考虑以下代码示例: #包括 #包括 模板 类某类 { 民众: std::function 一些...
如何从 std:::tuple 获取可变参数来解压另一个 std::tuple?
我正在尝试将模板参数列表(枚举类,而不是类型名)转换为 std::tuple 模板参数的相应类型名。我猜我是否能以某种方式给va命名......
我想重载(或专门化)一个可变参数函数,以便重载(或专门化)仅接受特定类型的参数。在 C++20 中我会写: #包括 #inc...
我可以在类定义内的非类型模板参数包上使用 `enable_if` 吗?
我想在可能固定数量的布尔值上模板化一个类,对它们进行计数,然后使用该数字作为基类的模板参数。像这样的东西 模板 我想在可能固定数量的布尔值上模板化一个类,对它们进行计数,然后使用该数字作为基类的模板参数。像这样的东西 template <int Dimensionality> struct Foo {}; // I want to inherit from this // helpers to compile-time count the true values among bools template <bool B, bool... Args> struct count_true { static constexpr int value = count_true<B>::value + count_true<Args...>::value; }; template <> struct count_true<true> { static constexpr int value = 1; }; template <> struct count_true<false> { static constexpr int value = 0; }; // I want something like this, pseudocode template <bool... Args> struct Bar : public Foo<count_true<Args...>::value> { Bar(bool... args) { // do something with the parameters static_assert(sizeof...(args) <= 1337); } }; 但我找不到办法做到这一点。 似乎有很多与使用 enable_if 作为函数参数包有关的问题,例如 在参数中强制执行单一类型的 C++ 参数包 使用enable_if检查参数包类型 或者在模板类型不用于继承的地方使用,例如 如何启用带有可变模板参数的类? 但在这个特殊情况下,这些都没有帮助。 “伪代码”无法编译,因为 bool... args 不是未扩展的参数包。 我想这样的东西可能会起作用,但事实并非如此,因为参数包必须是最后一个模板参数: template <class... Ts> struct Bar : public Foo<count_true<Ts..., std::enable_if_t<(std::is_same<Ts, bool>::value && ...), bool>>::value> { … } 有办法做到这一点吗?这个问题可能有点困惑,因为我真的不知道我在做什么。模板元编程。 但在这个特殊情况下,这些都没有帮助。 “伪代码” 无法编译,因为 bool... args 不是未扩展的参数 打包。 您可以使用 decltype() 扩展模板参数。此外,count_true可以简单地替换为折叠表达式。 template <bool... Args> struct Bar : public Foo<(Args + ... + 0)> { Bar(decltype(Args)... args) { // do something with the parameters static_assert(sizeof...(args) <= 1337); } };
给定一个可变参数模板参数包,我想使用内联 constexpr bool 和折叠表达式检查赋予它的所有类型是否都是唯一的。我尝试过这样的事情: 模板 给定一个可变参数模板参数包,我想使用 inline constexpr bool 和 fold 表达式 检查赋予它的所有类型是否都是唯一的。我尝试过这样的事情: template<class... T> inline static constexpr bool is_unique = (... && (!is_one_of<T, ...>)); 其中 is_one_of 是一个可以正确工作的类似布尔值。 但是无论我在 is_one_of 中放入什么内容,这一行都不会编译。这甚至可以使用折叠表达式来完成,还是我需要使用常规结构来实现此目的? 您的方法实际上不起作用,因为 is_one_of 需要使用类型 T 和所有其余类型 调用,不包括 T。无法通过单个参数包使用“折叠表达式”来表达这一点。我建议改用专业化: template <typename...> inline constexpr auto is_unique = std::true_type{}; template <typename T, typename... Rest> inline constexpr auto is_unique<T, Rest...> = std::bool_constant< (!std::is_same_v<T, Rest> && ...) && is_unique<Rest...> >{}; 用途: static_assert(is_unique<>); static_assert(is_unique<int>); static_assert(is_unique<int, float, double>); static_assert(!is_unique<int, float, double, int>); wandbox.org 上的实时示例 (感谢Barry使用折叠表达式进行简化。) --编辑-- 谷歌搜索我发现了一个有趣的解决方案,它给了我灵感来避免递归并避免很多警告 因此您可以定义类型的包装器 template <typename> struct wrapT { }; 以及从类型包装器继承的类型和整数包装器 template <typename T, std::size_t> struct wrapTI : public wrapT<T> { }; 接下来,您可以定义一个 foo 类,该类 递归 继承自 wrapTI template <typename T, typename = std::make_index_sequence<std::tuple_size<T>::value>> struct foo; template <typename ... Ts, std::size_t ... Is> struct foo<std::tuple<Ts...>, std::index_sequence<Is...>> : public wrapTI<Ts, Is>... { }; 现在is_unique可以是这样的 template <typename ... Ts> static constexpr bool isUnique = ( ... && std::is_convertible<foo<std::tuple<Ts...>>, wrapT<Ts>>::value ); 重点是,只有当foo<Ts...>从wrapT<T>继承一次(且仅一次)时,foo<Ts...>才能转换为wrapT<T>,也就是说,如果T出现一次(且仅出现一次)在Ts...。 以下是完整的编译示例 #include <tuple> #include <type_traits> template <typename> struct wrapT { }; template <typename T, std::size_t> struct wrapTI : public wrapT<T> { }; template <typename T, typename = std::make_index_sequence<std::tuple_size<T>::value>> struct foo; template <typename ... Ts, std::size_t ... Is> struct foo<std::tuple<Ts...>, std::index_sequence<Is...>> : public wrapTI<Ts, Is>... { }; template <typename ... Ts> static constexpr bool isUnique = ( ... && std::is_convertible<foo<std::tuple<Ts...>>, wrapT<Ts>>::value ); int main () { static_assert( true == isUnique<int, long, long long> ); static_assert( false == isUnique<int, long, long long, int> ); }
想要了解为什么下面的代码会导致: 类模板部分特化并不比主模板更特化 模板 结构...
Andrei 在 GoingNative 2012 的演讲中谈到了可变参数模板,并一度通过下面的示例解释了参数包扩展的工作原理。对此还很陌生
我正在尝试学习可变参数模板和函数。我不明白为什么这段代码不能编译: 模板 静态无效栏(T t){} 模板 静态...
以下哪些模仿 C++17 之前的折叠表达式的技术被认为是惯用的?
C++11 和 C++14 中的折叠式表达式:惯用方法? Q&A Variadic 模板包扩展的公认答案使用了常见的 pre-C++17(折叠表达式之前)appro...