Ich glaube nicht, dass es möglich ist, mit einer einzigen Funktion zu erreichen, was Sie wollen.
Selbst wenn Sie eine constexpr
Funktion entwickeln, glaube ich nicht, dass Sie erkennen können, wann die Laufzeit ausgeführt wird und wann die Kompilierzeit ausgeführt wird und wie Sie anders verfahren.
Aber Sie können verschiedene Funktionen entwickeln.
Durch beispielsweise eine Vorlage get<>()
, wobei das Template-Argument der Index ist, die nur mit einem Index zur Übersetzungszeit bekannt ist, verwendet werden können, und das kann ein static_assert()
zuführen, und ein at(std::size_t)
kann, dass ein Index erhalten, berechnet auf Laufzeit mit einer Laufzeitprüfung.
En passant:
1) Ich schlage vor, wie üblich in STL, die Verwendung von at()
für einen kontrollierte gebunden Zugang und ein operator[]()
für einen gebundenen unkontrollierten Zugang
2) und ich schlage vor, die Verwendung von ein vorzeichenloser Index oder Sie müssen überprüfen, ob der Index >= 0
ist.
Hier finden Sie ein funktionierendes Beispiel
#include <iostream>
#include <stdexcept>
template <class T, std::size_t Dim>
class Foo
{
private:
T _data[Dim];
public:
T const & operator[] (std::size_t idx) const
{ return _data[idx]; }
template <std::size_t IDX>
T const & get() const
{
static_assert(IDX < Dim, "out of range");
return this->operator[](IDX);
}
T const & at (std::size_t idx) const
{
if (idx >= Dim)
throw std::range_error("out of range");
return this->operator[](idx);
}
};
int main()
{
Foo<float, 2U> foo;
foo.get<0U>();
foo.get<1U>();
//foo.get<2U>(); // compiler error
for (auto i = 0U ; i < 5U ; ++i)
foo.at(i); // run time exception when i > 1
return 0;
}
danke, aktualisiert die Frage. – sharvey
Sie können __builtin_constant_p für GCC betrachten, aber es wird Ihnen wahrscheinlich keine perfekte Lösung bringen, da es einige wirklich seltsame Verhaltensweisen mit GCC gibt, wenn Sie versuchen, das zu tun, was Sie vorschlagen. –
Ihr 'foo [2]' Zugriff wird nicht im 'constexpr' Kontext gemacht, und Ihr Operator ist auch nicht 'constexpr'. Sie erhalten keinen Fehler bei der Kompilierung. Um Ihr Ziel zu erreichen, verwenden Sie 'assert' (was einen falschen 'consExpr'-Aufruffehler ergibt, wenn falsch) statt' static_assert'. –