Search code examples
c++variant

std::variant failing with templated class


I am messing around with std::variant however I Just cant seem to get it to work. it works fine when I use the primitive types of c++, but if I use a templated class I get the following compiler errors. there are a lot of errors that I cant understand. this is the build output. I don't know how much of this is useful.

1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\variant(1521,32): error C2672: 'invoke': no matching overloaded function found
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\variant(1531): message : see reference to class template instantiation 'std::_Variant_single_visit_result<_Callable,std::integer_sequence<_Ty,5>,std::variant<int,char,bool,std::string,A<int>> &>' being compiled
1>        with
1>        [
1>            _Callable=EventVisitor,
1>            _Ty=size_t
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\variant(1654): message : see reference to class template instantiation 'std::_Variant_all_visit_results_same<_Callable,_ListOfIndexVectors,std::variant<int,char,bool,std::string,A<int>> &>' being compiled
1>        with
1>        [
1>            _Callable=EventVisitor
1>        ]
1>C:\Users\jaden\source\repos\Project8\Project8\Main.cpp(55): message : see reference to function template instantiation 'void std::visit<EventVisitor,std::variant<int,char,bool,std::string,A<int>>&,void>(_Callable &&,std::variant<int,char,bool,std::string,A<int>> &)' being compiled
1>        with
1>        [
1>            _Callable=EventVisitor
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\variant(1522,1): error C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Ty1 &&,_Types2 &&...) noexcept(<expr>)'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\type_traits(1588): message : see declaration of 'std::invoke'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\variant(1522,1): message : With the following template arguments:
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\variant(1522,1): message : '_Callable=_Callable'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\variant(1522,1): message : '_Ty1=_First &'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\variant(1522,1): message : '_Types2={}'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\variant(1522,1): error C2780: 'unknown-type std::invoke(_Callable &&) noexcept(<expr>)': expects 1 arguments - 2 provided
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\type_traits(1582): message : see declaration of 'std::invoke'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\variant(1531,36): error C2955: 'std::_All_same': use of class template requires template argument list
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\variant(40): message : see declaration of 'std::_All_same'
1>Done building project "Project8.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

here is the code.

#include <iostream>
#include <vector>
#include <variant>

template<class T>
class A
{
public:
    T t;
};

struct EventVisitor
{
    void operator()(std::string s)
    {
        std::cout << s << std::endl;
    }
    void operator()(int i)
    {
        std::cout << i << std::endl;
    }
    void operator()(char c)
    {
        std::cout << c << std::endl;
    }
    void operator()(bool b)
    {
        if (b)
        {
            std::cout << "True" << std::endl;
        }
        else
        {
            std::cout << "False" << std::endl;
        }
    }
};

int main()
{
    // std::variant<int, char, bool, std::string> myVariant; works but if I add A<int> it breaks
    std::variant<int, char, bool, std::string, A<int>> myVariant;

    myVariant = true;
    std::visit(EventVisitor{}, myVariant);
}

Solution

  • Compiling std::visit fails, because your visitor has no handler for A<int>. You have to add it:

    void operator()(A<int> t) {}
    

    Or add a template function to your visitor to handle all types you might want to use.