Andrew
Andrew

Reputation: 119

Passing member function address of template class/struct as a function parameter

My aim is to get custom container method that returns another container with same elements but converted to a different type by passing a convertor member function address. Example in int main() below describes it in simplest way.

My problem is that I can't figure out proper declaration of such function parameter (if it is possible).

PS: I am using MSVC compiler.

template<typename container_type>
struct Container
{

    ...

    template
       <typename convert_type = container_type,
        typename = std::enable_if<!std::is_fundamental<container_type>::value>::type,
        typename = std::enable_if<!std::is_pointer<container_type>::value>::type>
    Container<convert_type> apply(convert_type (const container_type::*function)() const) const
            // error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
            // note: see reference to class template instantiation 'Container<container_type>' being compiled
            // error C2091: function returns function
    {
        Container<convert_type> result();
        result.reserve(this->size());

        for (const auto& i : *this)
        {
            result.push_back(i.*function());
        }

        return result;
    }
}



int main()
{
    Container<std::string> c = { "a", "b", "c" };
    Container<const char*> a = c.apply(&std::string::c_str);
}

Upvotes: 1

Views: 343

Answers (2)

Andrew
Andrew

Reputation: 119

Figured it out.

Remarks from R Sahu are correct! But there is also a 3rd mistake so I should add another answer to cover it completely.

1) There is unnecessary const before container_type. That is the reason of "error C2091: function returns function".

2) Wrong syntax for call of member function by pointer.

3) If one makes for example Container<SomeClass*> then not only apply() method will not be available, but that code will not compile as it is not SFINAE sufficient. The function pointer type should be template argument as well. So proper declaration of that function template should be:

 template
   <typename convert_type,
    typename = std::enable_if<!std::is_fundamental<container_type>::value>::type,
    typename = std::enable_if<!std::is_pointer<container_type>::value>::type,
    typename func_type = convert_type (type::*)() const>
Container<convert_type> apply(func_type function) const
{
    ...
    result.push_back((i.*function)());
    ...
}

Now that works.

Upvotes: 1

R Sahu
R Sahu

Reputation: 206717

To fix the missing return type, you may use

Container<convert_type> apply(convert_type (container_type::*function)() const) const

You'll have to fix the syntax to make the function call though.

result.push_back((i.*function)());

See a simpler example that demonstrates the idea at https://ideone.com/REb7Yu.

Upvotes: 1

Related Questions