0

I wanted to write the following code but got an error "no matches converting function 'handler' to type 'void (struct Parser::*)()". I use g++ 5.3.1 with options -std=c++14

With -std=17 I can use consrexpr T& std::array::operator[] (...) but now I wrote my class array.

What is wrong in this code?

#include <cstddef>
template <typename T, size_t _size> struct array {
T elements[_size];
constexpr size_t size() const noexcept { return _size; }
constexpr bool empty() const noexcept { return size() == 0; }
constexpr T& operator[](size_t index) noexcept { return elements[index]; }
};

struct Parser {
template <size_t index> void handler ();
};

template<> void Parser::handler<0> () {
}

template<> void Parser::handler<1> () {
}


constexpr auto createArrayHandlers () {
    array <void (Parser::*)(), 2> ans{&Parser::handler<0>, &Parser::handler<1>};
    for (size_t i = 0; i < ans.size(); ++i) {
        ans[i] = &Parser::handler<0>; //ok 
        ans[i] = &Parser::handler<i>; //error
    }
    return ans;
}
constexpr auto table = createArrayHandlers();
int main() {
    //table[parse_cmd(read_from_socket())]();
    return 0;
}

Now i have replaced this code with the following, but it executes at runtime

std::array<void (Parser::*)(), xxx> table {};
template <size_t i> size_t fillMemeberHandlerArray () {
    fillMemeberHandlerArray<i-1>();
    table[i] = &Parser::handler<i>;
    return i;
}

template<> size_t fillMemeberHandlerArray<0> () {
    table[0] = &Parser::handler<0>;
    return 0;
}
size_t const initTable = fillMemeberHandlerArray<table.size () - 1>();
1
  • Template parameter should be constant expression, i (from for) is not a constant expression. you may use std::index_sequence to initialize you array. Commented Apr 14, 2016 at 7:56

2 Answers 2

2
#include <utility>
#include <array>

namespace detail {
    template<std::size_t... Is>
    constexpr auto createArrayHandlers(std::index_sequence<Is...>) noexcept
     -> std::array<void(Parser::*)(), sizeof...(Is)>
    {
        return {{&Parser::handler<Is>...}};
    }
}

constexpr auto createArrayHandlers() noexcept
{
    return detail::createArrayHandlers(std::make_index_sequence<2>{});
}

constexpr auto table = createArrayHandlers();

Online Demo

As this does not use operator[] of the container to populate it, this works fine with std::array<> instead of rolling an approximation yourself.

Sign up to request clarification or add additional context in comments.

Comments

1

Template parameter should be constant expression, i (from for) is not a constant expression.

You may do

constexpr array<void (Parser::*)(), 2> createArrayHandlers () {
     return {{&Parser::handler<0>, &Parser::handler<1>}};
}

or use std::index_sequence to handle several compile time values.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.