2016-06-23 16 views
19

Supponendo che ho qualche modello di funzione F1:Come rilevare se una funz. è un constexpr? e contrassegna altre funzioni constexpr a seconda di esso?

template<typename f2> 
int f1(int i, int j) noexcept { 
    return i + j + f2(i, j); 
} 

c'è modo per determinare se f2(i, j) può essere un constexpr. (non importa che sia una funzione o un functor) e quindi contrassegnare f1<f2> come constexpr troppo?

Sto pensando di utilizzare SFINAE qui in qualche modo, ma non ho trovato come rilevare constexpr utilizzando type traits

+2

Sono anche interessato a questo. A volte, vuoi sovraccaricare un algoritmo a seconda di 'constexpr'ness, perché un'implementazione dell'algoritmo è' constexpr'able ma un'altra è più veloce. – KABoissonneault

+2

Inoltre, nota a lato ma: 'throw()' è deprecato, usa 'noexcept' se puoi (o rimuovilo dal tuo esempio, non è veramente rilevante per il tuo problema) – KABoissonneault

+0

@KABoissonneault, grazie, usando 'throw() 'è solo un'abitudine. –

risposta

11

È possibile contrassegnare come f1constexpr.

template<typename f2> 
constexpr int f1(int i, int j) noexcept { 
    return i + j + f2(i, j); 
} 

La funzione f1 modello sarebbe constexpr IIF f2 è.

se f2 non lo è, si otterrà l'errore solo quando si utilizza f1 in un'espressione di tempo di compilazione costante.

Demo

+0

Buona risposta, ma penso che quelle parentesi dopo 'noexcept' non siano valide – KABoissonneault

+0

@KABoissonneault: errore di battitura fisso. – Jarod42

+1

@AmaboCarab non hai usato una funzione * modello * nel tuo esempio. Penso che sia fondamentale per questo funzionare. – user2079303

6

Il modo più semplice per verificare se una funzione (ad esempio, foo) è constexpr è quello di assegnare il suo valore di ritorno ad un constexpr come di seguito:

constexpr auto i = foo(); 

se il valore restituito non è constexpr la compilazione fallirà.

Se si desidera un test SFINAE per verificare se una funzione (ad esempio, foo) è constexpr è possibile utilizzare il tipo di tratto std::integral_constant:

std::integral_constant<int, foo()>::value 

Live Demo

+4

Questo non sembra un amichevole di SFINAE – KABoissonneault

+0

@KABoissonneault Spero che tu sia coperto. – 101010

+0

Con la tua modifica, puoi mostrare un esempio di come questo potrebbe essere usato, ad esempio, per sovraccaricare una funzione? Perché, per quanto ne so, se si invia un valore non 'constexpr' a un modello, non verrà compilato, non "SFINAE". – KABoissonneault

0

Così, finalmente, utilizzando Jarod42 suggerimento, I'l scrivere e testato this example:

#include <string> 
std::string S = "123567876"; 

constexpr size_t p() noexcept { 
    return 10U; 
} 

template<const size_t = size_t()> 
constexpr size_t f(size_t i, size_t j) noexcept { 
    return std::move(i + j + S.size() + p()); 
} 

#include <iostream> 
int main() { 
    // static constexpr const auto v = f<>(1U, 2U); // error! 
    std::cout << f(1U, 2U) << "\n"; 
    return 0; 
} 

ora è il lavoro correttamente, ho provato usando GCC compilatore in linea sia con C + +11 e C + 14.


poter controllare il risultato sarà davvero constexpr se possibile, eliminando '+ S.size()':

... 
    return std::move(i + j + p()); 
... 

e decommentando valore constexpr:

... 
    static constexpr const auto v = f(1U, 2U); 
    std::cout << v << "\n"; 
... 

vedere here.


P. S. Grazie ragazzi!

+0

Perché stai chiamando 'std: : move' su dati fondamentali? 'size_t' è già banalmente costruibile, non ottieni nulla. Inoltre, non vedo più che cosa stia facendo effettivamente il tuo template – KABoissonneault

+0

@KABoissonneault lo chiamo solo per testare se sarebbe conforme. Ne ho bisogno come sto usando in un esempio significativamente più complicato, l'ho chiamato [Execute Member Function If It Is Present idiom] (http://www.codeproject.com/Tips/1029697/Execute-Member-Function-If -It-Is-Present), meglio vedere [ultima versione] (https://github.com/RussianEmpire/GenericCPPLib/blob/master/SRC/FuncUtils.h) nel repository. Ora lo aggiorno per farlo funzionare in modo condizionale con 'constexpr'. –

+0

["Se nessuna specializzazione del modello soddisfa i requisiti per una funzione constexpr o un costruttore constexpr quando viene considerata come una funzione o un costruttore non modello, il modello è mal formato, non è richiesta alcuna diagnostica."] (Http: // eel .is/C++ draft/dcl.constexpr # 6) –