2016-04-14 11 views
0

Ich wollte den folgenden Code schreiben, aber bekam eine Fehlermeldung "Nein entspricht Converting-Funktion 'Handler" auf' void (struct Parser :: *)() ". Ich benutze g ++ 5.3.1 mit Optionen -std = C++ 14Initialize Array von Zeigern zu Member-Funktionen zur Kompilierzeit mit Hilfe von consExpr

Mit -std = 17 Ich kann Consrexpr T & Std :: Array :: Operator [] (...), aber jetzt habe ich meine Klasse geschrieben Array.

Was ist in diesem Code falsch?

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

Jetzt habe ich diesen Code durch die folgende ersetzt, aber es führt zur Laufzeit

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>(); 
+0

Template-Parameter sollte konstanter Ausdruck sein, 'i' (von' for') ist kein konstanter Ausdruck. Sie können 'std :: index_sequence' verwenden, um Ihr Array zu initialisieren. – Jarod42

Antwort

1

Vorlage Parameter sollte konstanter Ausdruck sein, i (von for) ist kein konstanter Ausdruck.

können Sie

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

oder std::index_sequence mehrere Kompilierung Werte zu handhaben verwenden.

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

Da dies nicht operator[] des Behälters nicht verwendet um es zu bevölkern, funktioniert das gut mit std::array<> anstatt eine Annäherung selbst zu rollen.

+0

Ihr Code ist cool –