Dies ist eine Follow-up-Frage zu Detecting constexpr with SFINAE.SFINAE constexpr mit Std :: get
Ich möchte erkennen, ob ein Element eines Tupel (oder irgendetwas, das mit std::get
verwendet werden kann) constexpr ist. Also schrieb ich die folgenden Helfer ähnlich dem, was Xeo gab:
template<size_t> struct sfinae_true : std::true_type{};
template<size_t N, class T>
auto check(const T& arg) -> sfinae_true<(std::get<N>(arg),N)>;
template<size_t N, class>
std::false_type check(...);
Jetzt ist mein Testfahrer Code:
int main()
{
constexpr std::tuple<size_t, size_t> arg(4,5);
typedef decltype(check<0,decltype(arg)>(arg)) is_cexpr;
std::cout << "is constexpr? " << is_cexpr::value << '\n';
}
Dies ist jedoch immer druckt false
für mich! Um zu überprüfen, dass aus irgendeinem Grunde ist die falsche Überlastung nicht immer genannt wird, ich aus der falschen Überlastung kommentiert und den Compiler-Fehler:
jedochnote: candidate template ignored: substitution failure [with N = 0, T = const std ::tuple]: non-type template argument is not a constant expression
auto check(const T& arg) -> sfinae_true<(std::get(arg),0)>;
, ich weiß, dass ich std::get<N>(arg)
anrufen und einen constexpr Wert erhalten :
template<size_t N>
class A{};
int main()
{
constexpr std::tuple<size_t, size_t> arg(4,5);
A<std::get<0>(arg)> a_val;
}
Das kompiliert gerade fein.
- Warum erkennt die Prüffunktion den Kontextzugriff nicht richtig?
- Wie behebe ich das?
Ich testete dies mit Clang 3.8.0 auf Ubuntu 16.04.
edit:
Als weiterer Test auf Sams Antwort basiert, ich die Form versucht:
template<size_t N, class T>
auto check(const T& arg)
{
return sfinae_true<(std::get<N>(arg)*0)>();
}
Dieses vollständig aus dem Komma-Operator entledigt, die GCC kompiliert 5.4.0 just fine , aber Clang 3.8.0 beschwert sich immer noch über. Interessanterweise hebt Clang hervor, dass arg
selbst kein Constexpr ist.
Warum ist das Problem immer noch? Wie lauten die Regeln für die constexpr-Funktionsargumente?
Problem ist, dass 'arg' Parameter ist nicht 'constexpr' ... – Jarod42
(Um etwas zu erweitern, was ich denke @ Jarod42 bedeutet:' arg' ist ein Funktionsparameter ist nie als konstanter Ausdruck betrachtet, auch wenn das Argument, das Sie der Funktion übergeben, ein konstanter Ausdruck ist.) – dyp
Wie würde ich erkennen, ob das Ergebnis eines Funktionsaufrufs conexpr wäre, wenn diese Methode nicht funktioniert? Natürlich kann ich das Tupel als conexpr-Wert verwenden, indem ich das 'a_val'-Objekt konstruiere. – helloworld922