2017-08-02 5 views
2

J'essaie de trouver si une fonction lambda ou libre est const en utilisant la métaprogrammation C++ 14.Recherche si la fonction est const

Ma stratégie actuelle consiste à utiliser les std::is_reference, std::is_pointer et std::is_const pour chacun des arguments. (Actuellement en ignorant les variables globales ...)

donc l'objet de type qui vérifie ressemble à quelque chose comme ça ...

template <typename F> 
struct is_const_func: public function_traits<decltype(&F::operator())> {}; 

template <typename ClassType, typename ReturnType, typename... Args> 
struct is_const_func<ReturnType (ClassType::*)(Args...)> { 
    static const std::tuple<std::is_reference<Args>...> ref; 
    static const std::tuple<std::is_pointer<Args>...> ptr; 
    static const std::tuple<std::is_const<Args>...> con; 
    static const bool value = ? // Reduce(&&, (!ref && !ptr) || con) 
} 

Je veux savoir comment mettre en œuvre le value. Fondamentalement, je veux prendre l'élément ith de chacun des tuples et calculer (!ref[i] && !ptr[i]) || con[I] et réduire le tuple résultant avec &&, tous à la compilation.

Comment l'implémenter? Y a-t-il une meilleure façon de faire cette vérification?

+4

Qu'est-ce que cela signifie pour une fonction libre d'être const? – Barry

+0

Dans ce cas, je vérifie si tous les pointeurs et références transmis en arguments sont qualifiés 'const'. Ce n'est pas suffisant pour que la fonction ne change pas l'état du programme, mais je suppose qu'aucune variable globale n'est accédée/changée dans la fonction. – subzero

+2

Que feriez-vous même avec un tel trait? Vous ne pouvez jamais vraiment le faire correctement - en plus de l'état global, un 'const *' transmis peut toujours avoir un membre 'mutable' qui est modifié, etc. – Barry

Répondre

2

D'abord, trouvez une implémentation de C++ 17 std apply. Ensuite, écrivez all_of comme constexpr.

Ensuite, écrivez

struct all_of_t{ 
    constexpr all_of_t(){} 
    template<class...Bs> 
    constexpr bool operator()(Bs...bs)const{ return all_of(bs...); } 
}; 

Enfin:

static const std::tuple<std::integral_constant<bool, 
    (!std::is_reference<Args>{}&&!std::is_pointer<Args>{})||std::is_const<Args>{}>... 
> arg_state; 
static const bool value = apply(all_of_t, arg_state); 

chaque étape doit être facile à rechercher sur le SO.

+0

Plutôt que d'écrire 'all_of' en tant que fonctions' constexpr', il existe une bonne solution efficace de 'modèle constexpr bool all_of_v = Bs && ...;' en C++ 17, ou 'modèle constexpr bool all_of_v = std :: is_same , bools > :: value; 'where' bools' est un type comme 'template struct bools {};' – Justin

+1

@justin Je ferais moi-même ces valeurs constantes non constantes bool – Yakk