Frage

Ich bin derzeit dabei, überladungen von arithmetischen Operator für Tupel zu schreiben. Der Bediener iteriert über das Tupel, um den Betrieb auf jedem einzelnen Element durchzuführen. Hier ist die Definition für Operator +=:

template< typename... Ts, std::size_t I = 0 >
inline typename std::enable_if< I == sizeof... (Ts), std::tuple< Ts... >& >::type operator +=(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    return lhs;
}

template< typename... Ts, std::size_t I = 0 >
inline typename std::enable_if< I != sizeof... (Ts), std::tuple< Ts... >& >::type operator +=(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    std::get< I >(lhs) += std::get< I >(rhs);
    return operator +=< Ts..., I + 1 >(lhs, rhs);
}

Wenn ich versuche, den Betreiber anzurufen, kann GCC 4.6 leider nicht entscheiden, welche Überlastung er verwenden sollte. Zum Beispiel:

std::tuple< int, int, int, int > a = std::make_tuple(1, 2, 3, 4), b = std::make_tuple(5, 6, 7, 8);
a += b;

Ergibt den folgenden Fehler:

:/Workspace/raster/main.cpp:833:7:   instantiated from here
C:/Workspace/raster/main.cpp:809:45: error: no matching function for call to 'operator+=(std::tuple<int, int, int, int>&, const std::tuple<int, int, int, int>&)'
C:/Workspace/raster/main.cpp:809:45: note: candidates are:
C:/Workspace/raster/main.cpp:800:151: note: template<class ... Ts, unsigned int I> typename std::enable_if<(I == sizeof (Ts ...)), std::tuple<_TElements ...>&>::type operator+=(std::tuple<_TElements ...>&, const std::tuple<_TElements ...>&)
C:/Workspace/raster/main.cpp:806:83: note: template<class ... Ts, unsigned int I> typename std::enable_if<(I != sizeof (Ts ...)), std::tuple<_TElements ...>&>::type operator+=(std::tuple<_TElements ...>&, const std::tuple<_TElements ...>&)

Das ist seltsam, da die std::enable_if Die Bedingung sollte den unangemessenen Anruf ablehnen. Im Moment habe ich die folgende Problemumgehung, die eigentlich meine vorherige Implementierung war. Die obige Version ist in der Tat ein Vereinfachungsversuch.

template< std::size_t I, typename... Ts >
inline typename std::enable_if< I == sizeof... (Ts), std::tuple< Ts... >& >::type assignadd_impl(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    return lhs;
}

template< std::size_t I, typename... Ts >
inline typename std::enable_if< I != sizeof... (Ts), std::tuple< Ts... >& >::type assignadd_impl(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    std::get< I >(lhs) += std::get< I >(rhs);
    return assignadd_impl< I + 1, Ts... >(lhs, rhs);
}

template< typename... Ts >
inline std::tuple< Ts... >& operator +=(std::tuple< Ts... >& lhs, const std::tuple< Ts... >& rhs)
{
    return assignadd_impl< 0, Ts... >(lhs, rhs);
}

Dies kompiliert und funktioniert wie erwartet. Warum lehnt die vereinfachte Version ab zu kompilieren? Vielen Dank.

War es hilfreich?

Lösung

Wenn Sie explizit angegebene Vorlagenargumente für eine Funktion oder Klassenvorlage verwenden, müssen alle Vorlagenparameterpakete am Ende der Parameterliste der Gesamtvorlage angezeigt werden. Ziehen um Ts... Bis zum Ende des Vorlagenlisten listen die Aufrufe des Codes ab. Abschnitt 14.8.2.1 von Der aktuelle C ++ 0x Draft gibt an, dass Parameterpackungen, die sich nicht am Ende der Vorlagenparameterliste befinden operator+= In allen Fällen verursacht immer noch ein Sfinae -Fehler. Eine frühere Frage hat einen Link zu dem genauen Text, der ihm verbietet; IBMs Dokumentation sagt, dass es auch ein Fehler ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top