To jest kolejne pytanie do Detecting constexpr with SFINAE.SFINAE constexpr ze std :: get
Chcę wykryć, czy element krotki (lub czegokolwiek, co można użyć z std::get
) jest constexpr. Więc napisałem następujące pomocników podobne do tego, co dał Xeo:
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(...);
Teraz mój kierowca testowy kod:
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';
}
to jednak zawsze drukuje się false
dla mnie! Aby sprawdzić, które z jakiegoś powodu fałszywego przeciążenie nie jest zawsze o nazwie, ja wykomentowane fałszywego przeciążenia i pojawia się błąd kompilatora:
note: 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)>;
Jednak wiem, że mogę zadzwonić std::get<N>(arg)
i uzyskać wartość constexpr :
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;
}
To kompiluje się dobrze.
- Dlaczego funkcja kontrolna nie wykrywa prawidłowo elementu constexpr-ness?
- Jak to naprawić?
Testowałem to z Clang 3.8.0 na Ubuntu 16.04.
edit:
Jako dalsze badania w oparciu o odpowiedź Sam starałem postać:
template<size_t N, class T>
auto check(const T& arg)
{
return sfinae_true<(std::get<N>(arg)*0)>();
}
ten pozbywa się operatora przecinek, który całkowicie GCC 5.4.0 kompiluje dobrze , ale Clang 3.8.0 wciąż narzeka. Co ciekawe, Clang podkreśla, że sama arg
nie jest constexpr.
Dlaczego ten problem nadal występuje? Jakie są reguły dotyczące argumentów funkcji constexpr?
Problem polega na tym, że parametr 'arg' nie jest' constexpr' ... – Jarod42
(Aby nieco rozszerzyć to, co myślę @ Jarod42 znaczy: 'arg' jest parametrem funkcji nigdy nie jest traktowane jako wyrażenie ciągłe, nawet jeśli argument, który podajesz do funkcji, jest wyrażeniem stałym.) – dyp
Jak wykryłbym, jeśli wynik wywołania funkcji byłby constexpr, jeśli ta metoda nie działa? Oczywiście mogę użyć tej krotki jako wartości constexpr przez skonstruowanie obiektu 'a_val'. – helloworld922