简体   繁体   中英

C++ - Vector of function pointers inside class

I am making my own programming language. I made classes (like 'string' or 'int) that derive from the object class. I am making standard types like string and int so I have a base I can work off (expand my language with itself if that makes sense). Each standard type has a unordered_map of functions. I would love to hear a way to fix this/another approach.

When I run the program, I get this error that I don't understand:

C2664: 'std::pair<const _Kty,_Ty>::pair(std::pair<const _Kty,_Ty> &&)': cannot convert argument 2 from '_Ty' to 'const _Ty2 &'

It's referring to line 62. Where the error comes from:

c:\\program files (x86)\\microsoft visual studio\\2017\\community\\vc\\tools\\msvc\\14.16.27023\\include\\xmemory0 line:881

The code from xmemory0:

template<class _Objty,
        class... _Types>
        static void construct(_Alloc&, _Objty * const _Ptr, _Types&&... _Args)
        {   // construct _Objty(_Types...) at _Ptr
        ::new (const_cast<void *>(static_cast<const volatile void *>(_Ptr)))
            _Objty(_STD forward<_Types>(_Args)...);
        }

My code:

#include <iostream>
#include <unordered_map>
#include <string>
#include <functional>

struct Object;
typedef std::unordered_map<std::string, std::function<Object*(std::string*)>> stdtypefunc_map;

struct Object
{

};

struct StdType : public Object
{
    stdtypefunc_map functions;
};

struct stringtype : public StdType
{
    stringtype()
    {
        functions.emplace("GetValue", &stringtype::GetValue);
    }

    Object* GetValue(std::string args[])
    {
        std::cout << "GetValue()" << std::endl;
    }
};

int main()
{
    stringtype s;
    return 0;
}

In your code, line 62 is this statement:

functions.emplace("GetValue", &stringtype::GetValue);

functions is an std::unordered_map whose key_type is std::string and mapped_type is std::function<Object*(std::string*)> .

emplace() constructs a new std::unordered_map::value_type in the map, passing the values you specify to the value_type 's constructor. In this case, that value_type is a std::pair<const std::string, std::function<Object*(std::string*)>> , and you are passing in 2 values to constructor the std::pair with.

The error message you are seeing is basically saying that the compiler can't convert &stringtype::GetValue to std::function<Object*(std::string*)> . For example, here is a simplified example that reproduces the same failure, and GCC gives a VERY DETAILED error message explaining why it failed (which is too large to post here, so I'll post only the relevant pieces):

https://ideone.com/qVLkQd

#include <iostream>
#include <unordered_map>
#include <string>
#include <functional>

struct Object;
typedef std::unordered_map<std::string, std::function<Object*(std::string*)>> stdtypefunc_map;

struct Object
{

};

struct StdType : public Object
{
    stdtypefunc_map functions;
};

struct stringtype : public StdType
{
    stringtype()
    {
        functions.emplace("GetValue", &stringtype::GetValue);
    }

    Object* GetValue(std::string args[])
    {
        std::cout << "GetValue()" << std::endl;
    }
};

int main()
{
    stringtype s;
    return 0;
}
/usr/include/c++/6/ext/new_allocator.h:120:4: error: no matching function for call to ‘std::pair<const std::__cxx11::basic_string<char>, std::function<Object*(std::__cxx11::basic_string<char>*)> >::pair(const char [9], Object* (stringtype::*)(std::__cxx11::basic_string<char>*))’
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
/usr/include/c++/6/ext/new_allocator.h:120:4: note:   cannot convert ‘std::forward<Object* (stringtype::*)(std::__cxx11::basic_string<char>*)>((* & __args#1))’ (type ‘Object* (stringtype::*)(std::__cxx11::basic_string<char>*)’) to type ‘const std::function<Object*(std::__cxx11::basic_string<char>*)>&’
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...

Which makes sense. You can't store a pointer-to-member-method for a non-static method into a std::function unless you take into account that it will need an object instance to call the method on. Such as by using std::bind() to bind an object instance with the pointer-to-member-method:

using std::placeholders::_1;
functions.emplace("GetValue", std::bind(&stringtype::GetValue, this, _1));

Or, by using a lambda to capture the object:

functions.emplace("GetValue", [this](std::string *args){ return this->GetValue(args); });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM