Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

std::variant template deduction when isolating containing type

I have been making a serializer today and am having trouble getting it to work with variants.

I have used this process before for various other things where I keep trimming off the type till I get to the one type I need. However, it seems VC++ can’t deduce it this time.

Here is a complete example of the error.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

 #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 );
 }

I am confused why this is not working. It should check to see if it T1 is the type the variant contains. If it is not then it checks if there are more types to check and calls the same serialize_variant function with one less type when there is, otherwise it just returns. It is throwing a no matching overload for serialize_variant on the recursive call and it says it cannot deduce T1.

Can anyone shed some light on why this is failing to compile?

It is the following errors I am getting

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'   

Thanks.

>Solution :

The branch with sizeof...(Rest) >= 1 must also be valid when the condition is false, but it isn’t. You can get it discarded when the condition is false via if constexpr. Moreoever you were trying to return something but the return type is 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

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading