2016-11-12 6 views
10

Ich habe versucht, Code unten in Wandbox:std :: anwenden und konstanter Ausdruck?

#include <array> 
#include <iostream> 
#include <tuple> 
#include <typeinfo> 
#include <functional> 
#include <utility> 


int main() 
{ 
    constexpr std::array<const char, 10> str{"123456789"}; 
    constexpr auto foo = std::apply([](auto... args) constexpr { std::integer_sequence<char, args...>{}; } , str); 
    std::cout << typeid(foo).name(); 
} 

und der Compiler hat mir gesagt, dass args... Ausdruck nicht konstant sind. Was ist los?

+7

Es sei denn, dies in C++ 1z geändert hat, können Sie nicht constexpr Funktionsparameter haben. Das heißt, jede Funktion muss annehmen, dass sie mit Laufzeitparametern aufgerufen werden kann, und dann ist Ihr Lambda nicht sinnvoll. – krzaq

+0

@krzaq Was für eine Schande ... – Cu2S

Antwort

4

Alle constexpr-Funktionen müssen sowohl conexpr als auch nicht gültig sein, auch wenn sie als conetexpr gekennzeichnet sind.

Es gibt einen Vorschlag für ein consExpr-Literal, das Zeichen als nicht typisierte Vorlagenparameter übergeben hat. Dann könnte "hello"_bob direkt auf ein Parameterpaket erweitert werden.

Ein anderer Ansatz ist, können Sie std::integral_constant<T, t> an den Lambda durch einen Mechanismus übergeben, wie meine indexer. Dann ist die Umwandlung in T consExpr sogar, obwohl die Variable nicht. Dies hilft dir nicht mit "hello" zu einer Sequenz.

8

Funktionsparameter können nicht mit constexpr beschriftet werden. Daher können Sie sie nicht an Stellen verwenden, an denen konstante Ausdrücke erforderlich sind, wie bei nicht typisierten Vorlagenargumenten.

Um das zu tun, was Sie tun möchten, benötigen Sie eine Art Kompilierzeit-String-Verarbeitung, basierend auf Vorlagenargumenten.

5

Was möchten Sie können ohne std::apply erfolgen:

#include <array> 
#include <iostream> 
#include <tuple> 
#include <typeinfo> 
#include <functional> 
#include <utility> 
#include <type_traits> 

template <std::size_t N, class = std::make_index_sequence<N>> 
struct iterate; 

template <std::size_t N, std::size_t... Is> 
struct iterate<N, std::index_sequence<Is...>> { 
    template <class Lambda> 
    constexpr auto operator()(Lambda lambda) { 
     return lambda(std::integral_constant<std::size_t, Is>{}...); 
    } 
}; 

int main() 
{ 
    constexpr std::array<const char, 10> str{"123456789"}; 
    constexpr auto foo = iterate<str.size()>{}([](auto... is) constexpr { return std::integer_sequence<char, str[is]...>{}; }); 
    std::cout << typeid(foo).name(); 
} 

[live demo]

+2

Ich bekomme, dass es funktioniert, aber ... sollte es? – krzaq

+0

Ich denke jetzt eigentlich sollte es nicht aber noch nicht sicher sein ...:/ –

+0

Wenn der Str außerhalb von Main definiert wurde, dann wird es keine Zweifel daran geben ... –

Verwandte Themen