模板元编程是一种元编程技术,其中编译器使用模板生成临时源代码,该代码由编译器与其余源代码合并然后编译。
我想根据模板参数的变量数量的类型生成一个字符串文字。每种类型都应翻译成字符串文字(1 个或多个字符),然后是文字 ...
我需要定义一个枚举 枚举类 MyEnum { MyEnum1 = 0x0001, MyEnum2 = 0x0002, MyEnum3 = 0x0004, MyEnum4 = 0x0008, MyEnum5 = 0x0010 }; 所以基本上这些枚举值是由
我想在可变模板类中创建一个函数类型声明。该函数需要接受模板参数列表对应的参数。我想弄清楚是否...
这段检测默认运算符的代码为什么从来不选择特化部分是有原因的吗?
此代码始终打印 0,我不明白为什么。我错过了什么吗? #include #include 模板 结构
检查是否可以计算 lambda constexpr (C++17)
我正在尝试找到一种方法来检查 lambda 是否可以持续评估或 不在 C++17 中。假设我要检查的 lambda 不带 参数。 我偶然发现 这 问题,谁接受...
对于实现条件类型,我非常喜欢 std::conditional_t,因为它使代码简短且可读性强: 模板 使用 bit_type = std::conditional_t 对于实现条件类型,我非常喜欢std::conditional_t,因为它使代码简短且可读性强: template<std::size_t N> using bit_type = std::conditional_t<N == std::size_t{ 8 }, std::uint8_t, std::conditional_t<N == std::size_t{ 16 }, std::uint16_t, std::conditional_t<N == std::size_t{ 32 }, std::uint32_t, std::conditional_t<N == std::size_t{ 64 }, std::uint64_t, void>>>>; 使用起来非常直观: bit_type<8u> a; // == std::uint8_t bit_type<16u> b; // == std::uint16_t bit_type<32u> c; // == std::uint32_t bit_type<64u> d; // == std::uint64_t 但由于这是一个纯条件类型,因此必须有一个默认类型 - void,在这种情况下。因此,如果 N 是任何其他值,则该类型产生: bit_type<500u> f; // == void 现在不能编译了,但是 yielding 类型仍然有效。 意味着你可以说 bit_type<500u>* f; 并且会有一个有效的程序! 那么有没有什么好的方法可以让遇到条件类型的fail case时编译失败呢? 立即有一个想法是将最后一个std::conditional_t替换为std::enable_if_t: template<std::size_t N> using bit_type = std::conditional_t<N == std::size_t{ 8 }, std::uint8_t, std::conditional_t<N == std::size_t{ 16 }, std::uint16_t, std::conditional_t<N == std::size_t{ 32 }, std::uint32_t, std::enable_if_t< N == std::size_t{ 64 }, std::uint64_t>>>>; 问题是模板总是被完全评估,这意味着 std::enable_if_t 总是被完全评估 - 如果 N != std::size_t{ 64 } 就会失败。呃 我目前的解决方法是相当笨拙地引入一个结构和 3 using 声明: template<std::size_t N> struct bit_type { private: using vtype = std::conditional_t<N == std::size_t{ 8 }, std::uint8_t, std::conditional_t<N == std::size_t{ 16 }, std::uint16_t, std::conditional_t<N == std::size_t{ 32 }, std::uint32_t, std::conditional_t<N == std::size_t{ 64 }, std::uint64_t, void>>>>; public: using type = std::enable_if_t<!std::is_same_v<vtype, void>, vtype>; }; template<std::size_t N> using bit_type_t = bit_type<N>::type; static_assert(std::is_same_v<bit_type_t<64u>, std::uint64_t>, ""); 这通常有效,但我不喜欢它,因为它添加了太多东西,我还不如使用模板专业化。它还将 void 保留为特殊类型 - 因此它在 void 实际上是分支的收益的情况下不起作用。有可读的、简短的解决方案吗? 你可以通过添加一个间接级别来解决这个问题,这样最外层的 conditional_t 的结果就不是一个类型,而是一个需要 ::type 才能应用到它的元函数。然后使用 enable_if 而不是 enable_if_t 这样您就不会访问 ::type 除非确实需要它: template<typename T> struct identity { using type = T; }; template<std::size_t N> using bit_type = typename std::conditional_t<N == std::size_t{ 8 }, identity<std::uint8_t>, std::conditional_t<N == std::size_t{ 16 }, identity<std::uint16_t>, std::conditional_t<N == std::size_t{ 32 }, identity<std::uint32_t>, std::enable_if<N == std::size_t{ 64 }, std::uint64_t>>>>::type; 在此版本中,最终分支中的类型是 enable_if<condition, uint64_t>,它始终是有效类型,并且只有在实际采用该分支并且需要 enable_if<false, uint64_t>::type 时才会出现错误。当采用较早的分支之一时,您最终使用 identity<uintNN_t>::type 作为一种较小的整数类型,并且 enable_if<false, uint64_t> 没有嵌套类型(因为您不使用它)并不重要。 只是为了好玩......使用std::tuple和std::tuple_element完全避免std::conditional怎么样? 如果您可以使用 C++14(因此模板变量和模板变量的特化),您可以编写一个模板变量用于转换大小/元组中的索引 template <std::size_t> constexpr std::size_t bt_index = 100u; // bad value template <> constexpr std::size_t bt_index<8u> = 0u; template <> constexpr std::size_t bt_index<16u> = 1u; template <> constexpr std::size_t bt_index<32u> = 2u; template <> constexpr std::size_t bt_index<64u> = 3u; 所以bit_type变成 template <std::size_t N> using bit_type = std::tuple_element_t<bt_index<N>, std::tuple<std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t>>; 如果你只能使用 C++11,你可以开发一个 bt_index() constexpr 返回正确(或不正确)值的函数。 您可以验证是否满意 static_assert( std::is_same_v<bit_type<8u>, std::uint8_t>, "!" ); static_assert( std::is_same_v<bit_type<16u>, std::uint16_t>, "!" ); static_assert( std::is_same_v<bit_type<32u>, std::uint32_t>, "!" ); static_assert( std::is_same_v<bit_type<64u>, std::uint64_t>, "!" ); 以及使用 bit_type 和不受支持的尺寸 bit_type<42u> * pbt42; 导致编译错误。 -- 编辑 -- 正如 Jonathan Wakely 所建议的,如果你可以使用 C++20,那么 std::has_single_bit()(以前是 std::ispow2())和 std::bit_width()(以前是 std::log2p1()),你可以简化很多:你可以完全避免bt_index而简单地写 template <std::size_t N> using bit_type = std::tuple_element_t<std::has_single_bit(N) ? std::bit_width(N)-4u : -1, std::tuple<std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t>>;
所以我正在尝试创建一个类型特征来说明两个“外部”类类型是否相同。 IE。 std::vector 与 std::vector 相同,我不关心任何内部参数...
假设我有这个: 模板 结构A { A() { 标准::计算<< W << " - " << H << std::endl; } }; And I also have another s...
在 C++ 中,创建一个验证某个类具有特定方法的概念,问题是该方法可以接受任意数量的参数
我正在尝试创建一个概念来验证类是否具有特定方法。该约束应仅检查具有此类名称的方法是否存在以及特定返回类型。它不应该放
我正在尝试将数组签名扩展为 size_t 模板参数包。 我正在使用“现代模板元编程:纲要”幻灯片 24 中的示例,(Walter Brown,CppCo ...
我正在尝试从容器中提取值类型。事实证明,大多数 std 容器都有一个 value_type,但不幸的是,maps 将它用于其他目的。 所以,我试图创建一个代码...
我有一个包含多个模板方法的类,即: 类 MessageEndpoint { 民众: 使用 SupportedMessages = boost::mp11::mp_list 我有一个包含多个模板方法的类,即: class MessageEndpoint { public: using SupportedMessages = boost::mp11::mp_list<messaging::MessageType1, messaging::MessageType2, messaging::MessageTypeN>; public: virtual ~MessageEndpoint(); public: template <typename MessageType> UID subscribe(const UID &publisher_uid, std::function<void(const MessageType &)> callback); template <typename MessageType> void send_message(const MessageType &message); template <typename MessageType> void send_message(MessageType &&message); } 必须为几种类型预实例化这些方法(在SupportedMessages列表中)。 当然,我可以为列表中的每个类做这样的事情: // Instantiation. template <> UID subscribe<messaging::MessageType1>(const UID &publisher_uid, std::function<void(const messaging::SpikeMessage &)> callback); template <> void MessageEndpoint::send_message<messaging::MessageType1>(messaging::MessageType1 &&message); template <> void MessageEndpoint::send_message<messaging::MessageType1>(const messaging::MessageType1 &message); 但这又长又丑。我该怎么做,像这样: template_for<MessageEndpoint::SupportedMessages, T, { template <> UID subscribe<T>(const UID &publisher_uid, std::function<void(const T &)> callback); template <> void MessageEndpoint::send_message<T>(T &&message); template <> void MessageEndpoint::send_message<T>(const T &message); }> 这可能吗?我如何使用 Boost::MP11 做到这一点? 我找到了一个可接受的解决方案。 一些部分解决方案(感谢@davis-herring 和@quxflux): 为一组类型专门化许多模板. 一组类型的模板专业化. 条件: 我们不能用标量替换模板,因为我们有很多组合。即使我们有两种类型。 我们不能在另一个代码的编译过程中实例化模板。 IE。这是 Python 中使用的库。 我们不想在添加新类型时总是手动创建新实例。 有关实例化的所有信息必须在编译时已知。 没有用于创建“实例化循环”的 C++ 语言结构。 所以只有一种方法可以解决这个问题:使用预处理器。 方便的方法是使用 Boost.Preprocessor library. 我将展示简化示例:实体关系基础实现。 这个例子可能不会编译,但它所基于的真实代码是有效的。 namespace my_code { // There are comma separated types. // I.e. declared somewhere in the type traits library. // These will be used by preprocessor macroses. // MUST be declared without parentheses. #define ALL_ENTITIES EntityType1, EntityType2, EntityTypeN // MP11 list creation: for example, how to work with types lists. using AllEntites = boost::mp11::mp_list<ALL_ENTITIES>; #define ALL_RELATIONS RelationOneToMany, RelationOneToOne using AllRelations = boost::mp11::mp_list<ALL_RELATIONS>; class ER { public: // Some metaprogramming stuff. using AllEntityContainers = boost::mp11::mp_transform<EntityContainer, AllEntites>; using AllRelationContainers = boost::mp11::mp_transform<RelationContainer, AllRelations>; using AllEntityVariants = boost::mp11::mp_rename<AllEntityContainers, std::variant>; using AllRelationVariants = boost::mp11::mp_rename<AllRelationContainers, std::variant>; public: using EntityContainer = std::vector<AllEntityVariants>; using RelationContainer = std::vector<AllRelationVariants>; public: // Templates must be instantiated explicitly. template <typename EntityType> void add_entity(EntityType &&entity); template <typename EntityType> EntityType &get_entity(const UID &entity_uid); template <typename EntityType> const EntityType &get_entity(const UID &entity_uid) const; public: // Another templates group must be instantiated explicitly. template <typename RelationType> void add_relation(RelationType &&relation); template <typename RelationType> RelationType &get_relation(const UID &relation_uid); template <typename RelationType> const RelationType &get_relation(UID &relation_uid) const; private: template <typename T, typename VT> typename std::vector<VT>::iterator find_elem(const knp::core::UID &uid, std::vector<VT> &container); private: EntityContainer entities_; RelationContainer relations_; }; } // namespace my_code. 实施: namespace my_code { // This template used in another template methods and will be instantiated automatically. template <typename T, typename VT> typename std::vector<VT>::iterator ER::find_elem(const UID &uid, std::vector<VT> &container) { auto result = std::find_if( container.begin(), container.end(), [&uid](VT &p_variant) -> bool { constexpr auto type_n = boost::mp11::mp_find<VT, T>(); if (p_variant.index() != type_n) return false; return uid == (std::get<type_n>(p_variant)).get_uid(); }); return result; } // Must be instantiated explicitly. template <typename EntityType> void ER::add_entity(EntityType &&entity) { entities_.emplace_back(ER::AllEntitiesVariants(entity)); } // Must be instantiated explicitly. template <typename EntityType> EntityType &ER::get_entity(const UID &entity_uid) { auto r = find_elem<EntityType, AllEntityVariants>(entity_uid, entities_); if (r != entities_.end()) return std::get<EntityType>(*r); throw std::runtime_error("Can't find entity!"); } // Must be instantiated explicitly. template <typename EntityType> const EntityType &ER::get_entity(const UID &entity_uid) const { return const_cast<ER*>(this)->get_entity<EntityType>(entity_uid); } // Must be instantiated explicitly. void ER::add_relation(ER::AllRelationVariants &&relation) { relations_.emplace_back(relation); } // Must be instantiated explicitly. template <typename RelationType> void ER::add_relation(RelationType &&relation) { add_relation(ER::AllRelationVariants(relation)); } // Must be instantiated explicitly. template <typename RelationType> RelationType &ER::get_relation(const UID &relation_uid) { auto r = find_elem<RelationType, AllRelationVariants>(relation_uid, relations_); if (r != relations_.end()) return std::get<RelationType>(*r); throw std::runtime_error("Can't find relation!"); } // Must be instantiated explicitly. template <typename RelationType> const RelationType &ER::get_relation(const UID &relation_uid) const { return const_cast<ER *>(this)->get_relation<RelationType>(relation_uid); } // Entity methods instantiation macro, which will be called in cycle // by preprocessor. #define INSTANCE_ENTITY_FUNCTIONS(n, template_for_instance, neuron_type) \ template void ER::add_entity<Entity<entity_type>>(Entity<entity_type> &&); \ template Entity<entity_type> &ER::get_entity<Entity<entity_type>>(const UID &); \ template const Entity<entity_type> &ER::get_entity<Entity<entity_type>>(const knp::core::UID &) const; // Relation methods instantiation macro, which will be called in cycle // by preprocessor. #define INSTANCE_RELATION_FUNCTIONS(n, template_for_instance, relation_type) \ template void ER::add_relation<Relation<relation_type>>(Relation<relation_type> &&); \ template Relation<relation_type> &ER::get_relation<Relation<relation_type>>(const UID &); \ template const Relation<relation_type> &ER::get_relation<Relation<relation_type>>(const UID &) const; // Entities instantiation cycle. BOOST_PP_SEQ_FOR_EACH(INSTANCE_ENTITY_FUNCTIONS, "", BOOST_PP_VARIADIC_TO_SEQ(ALL_ENTITIES)) // Relations instantiation cycle. BOOST_PP_SEQ_FOR_EACH(INSTANCE_RELATION_FUNCTIONS, "", BOOST_PP_VARIADIC_TO_SEQ(ALL_RELATIONS)) } // namespace my_code 这段代码对我来说已经足够了,但如果有人愿意,他可以使用这种“技术”做出更复杂的东西。 例如,BOOST_PP_SEQ_FOR_EACH_PRODUCT可以用来做几个类的所有组合列表(有些问题是必须要解决的,即相等的类组合实例化几次,但这是可能的)。
我如何创建一个基于 std::variant 的函数数组,它由一些消息类型组成,它们将从 io 字节中解码,以便我可以快速访问正确的函数...
在 C# 和 Java 领域工作多年后,我最近又回到了 C++ 领域,并且很喜欢 C++ 在我缺席的情况下的发展方向(从 C++11 开始,现在正在学习 C++20!)。模板的力量真的是
我正试图从模板元编程开始。我写了这样的简单构造:模板 Class Fact { public: enum { result = N * Fact ::result }; }; template& ...
模板 C fnc(); 模板<> int fnc(){return 0;}模板。 C var; template <> int var = 0; /编译错误 int main() { }有一个特殊化的...
如果没有溢出,我需要一个函数给我类型为'std::ratio_multiply'的函数,如果溢出,则给我原始比率类型的列表。
如果a,b,c,...表示类型,那么让(a,b)成为std::pair类型。 我正在寻找映射F,使得F : (((((a,b),c),d),...))) -> std::tuple 这个是否存在下...
我有这样的代码:模板 结构 Bind {模板 static auto func(Args&&... args) { return std::invoke(Function, args...)....
我有一个结构,它在模板参数上取enum类的值。 结构类型 { public: static constexpr int VALUE = static_cast (EnumValue); }; 。