std::variant 隔离包含类型时的模板推导

std::variant template deduction when isolating containing type

我今天一直在制作序列化器,但在使用变体时遇到了问题。

我之前用这个过程来处理其他各种事情,我不断地修剪类型,直到我得到我需要的一种类型。不过这次好像VC++推不出来

这是错误的完整示例。

 #include <type_traits>
 #include <variant>
 #include <iostream>
 #include <sstream>

 void serialize( auto& s, float v ) {
     std::cout << "serialize float";
 }
 void serialize( auto& s, int v ) {
     std::cout << "serialize int";
 }
 void serialize( auto& s, bool v ) {
     std::cout << "serialize bool";
 }
 namespace detail
 {
     template<typename VariantT, typename T1, typename ...Rest>
     void serialize_variant( auto& s, const VariantT& v ) {
         if ( std::holds_alternative<T1>( v ) )
             return serialize( s, std::get<T1>( v ) );
         else if ( sizeof...(Rest) >= 1 )
             return serialize_variant<VariantT, Rest...>( s, v );
         else return;
     }
 }
 template<typename ...VariantTs>
 void serialize( auto& s, const std::variant<VariantTs...>& v ) {
      detail::serialize_variant<std::variant<VariantTs...>, VariantTs...>( s, v );
 }
 int main() {
     std::stringstream s{};
     std::variant<float, int, bool> x = true;
     serialize( s, x );
 }

我很困惑为什么这不起作用。它应该检查 T1 是否是变体包含的类型。如果不是,则它会检查是否有更多类型要检查,并在存在时用更少的类型调用相同的 serialize_variant 函数,否则它只是 returns。它在递归调用中为 serialize_variant 抛出一个不匹配的重载,它说它不能推断出 T1.

谁能解释一下编译失败的原因?

我得到的是以下错误

Error   C2672   'serialize_variant': no matching overloaded function found   
Error   C2783   'void detail::serialize_variant(_T0 &,const VariantT &)': could not deduce 
    template argument for 'T1'   

谢谢。

带有sizeof...(Rest) >= 1的分支在条件为false时也必须有效,但事实并非如此。当条件为 false 时,您可以通过 if constexpr 将其丢弃。此外,无论您尝试 return 什么,但 return 类型是 void

 namespace detail
 {
     template<typename VariantT, typename T1, typename ...Rest>
     void serialize_variant( auto& s, const VariantT& v ) {
         if ( std::holds_alternative<T1>( v ) )
             /*return*/ serialize( s, std::get<T1>( v ) );
         else { 
            if constexpr ( sizeof...(Rest) >= 1 )
             /*return*/ serialize_variant<VariantT, Rest...>( s, v );
            else return;
         }
     }
 }

Complete example