使用std::tuple<void>创建模板类shared_ptr时出现‘形成void引用’错误
问题分析与解决
你遇到的问题核心在于std::make_shared的实现会触发C<std::tuple<void>>的完整类型实例化,而部分编译器在处理std::conditional_t时,会意外实例化未被选中的分支(std::optional<std::tuple<void>>)。
当std::optional<std::tuple<void>>被实例化时,标准库的std::optional实现会尝试生成与模板参数相关的引用类型。虽然std::tuple<void>本身是合法类型,但部分标准库实现中,实例化std::optional<std::tuple<void>>会间接尝试创建void&类型(比如通过std::add_lvalue_reference_t),而C++禁止创建void的引用,因此触发编译错误。
而make_unique或直接声明C<std::tuple<void>>对象时,编译器不需要实例化C内部的ResultOptionalType别名(只有当这个别名被实际使用时才会触发实例化),因此不会触发错误。
解决方案
用模板特化替代std::conditional_t,完全避免未选中分支的实例化:
#include <memory> #include <optional> #include <tuple> #include <variant> template<typename Type> class C { public: using ResultOptionalType = std::optional<Type>; }; // 针对std::tuple<void>的特化版本 template<> class C<std::tuple<void>> { public: using ResultOptionalType = std::monostate; }; int main() { using ResultOptionalType = std::conditional_t<std::is_same_v<std::tuple<void>, std::tuple<void>>, std::monostate, std::optional<std::tuple<void>>>; using T = std::optional<std::tuple<void>>; C<std::tuple<void>> c1; auto c2 = std::make_unique<C<std::tuple<void>>>(); auto c3 = std::make_shared<C<std::tuple<void>>>(); // 现在可正常编译 }
这个方案通过特化C类,让C<std::tuple<void>>的定义完全不涉及std::optional<std::tuple<void>>,从根源上避免了非法引用类型的生成。
内容的提问来源于stack exchange,提问作者dpons
相关产品推荐
相关产品推荐

