2016-12-22 1 views
1

J'ai une base de données d'objets et j'aimerais compter combien sont d'un type particulier au moment de la compilation, mais j'ai un peu de mal à le compiler. Voici un exemple réduit de ce que j'ai essayé jusqu'ici, mais cela échoue à compiler avec "error: call to function 'do_count' qui n'est ni visible dans la définition du template ni trouvé par la recherche dépendant de l'argument"Comment faire un compte constexpr basé sur un trait de type

Y a-t-il un meilleur moyen?

#include <cstdint> 
#include <type_traits> 
#include <cstddef> 

struct unused_tag {}; 
struct used_tag {}; 

template<std::size_t X> 
struct traits { 
    using type = unused_tag; 
}; 

template<> 
struct traits<7> { 
    using type = used_tag; 
}; 

static constexpr const std::size_t MAX_X = 10; 

template<std::size_t X = 0> 
constexpr 
std::enable_if_t< 
    !std::is_same<typename traits<X>::type, unused_tag>::value, 
    std::size_t> 
do_count() 
{ 
    return do_count<X + 1>() + 1; 
} 

template<std::size_t X = 0> 
constexpr 
std::enable_if_t< 
    std::is_same<typename traits<X>::type, unused_tag>::value, 
    std::size_t> 
do_count() 
{ 
    return do_count<X + 1>(); 
} 

template<> 
constexpr std::size_t do_count<MAX_X>() 
{ 
    return 0; 
} 

static constexpr const std::size_t COUNT = do_count(); 
+1

Qu'est-ce que ce regard « base de données » comme? Pouvez-vous fournir une meilleure explication avec des exemples de certaines entrées et sorties désirées? Sur quelle ligne est cette erreur? – qxz

Répondre

0

Il semble que vous avez trouvé une autre solution à votre problème, mais voici une solution à l'aide std :: enable_if si vous étiez curieux. Le problème est que l'appel de do_count depuis la version! Std :: is_same < ...> ne peut pas voir la version std :: is_same < ...> donc, comme dit le compilateur, il n'est pas visible depuis le site d'appel et ne peut pas être résolu. Pour résoudre ce problème, il suffit de faire une déclaration forward du fichier std :: is_same < ...>.

Pour exemple, ce qui suit pour moi compile:

#include <cstdint> 
#include <type_traits> 
#include <cstddef> 

struct unused_tag {}; 
struct used_tag {}; 

template<std::size_t X> 
struct traits { 
    using type = unused_tag; 
}; 

template<> 
struct traits<9> { 
    using type = used_tag; 
}; 

static constexpr const std::size_t MAX_X = 10; 

// 
// forward declaration 
// 
template<std::size_t X = 0> 
constexpr 
std::enable_if_t< 
    std::is_same<typename traits<X>::type, unused_tag>::value, 
    std::size_t> 
do_count(); 

template<std::size_t X = 0> 
constexpr 
std::enable_if_t< 
    !std::is_same<typename traits<X>::type, unused_tag>::value, 
    std::size_t> 
do_count() 
{ 
    return do_count<X + 1>() + 1; 
} 

template<std::size_t X> 
constexpr 
std::enable_if_t< 
    std::is_same<typename traits<X>::type, unused_tag>::value, 
    std::size_t> 
do_count() 
{ 
    return do_count<X + 1>(); 
} 

template<> 
constexpr std::size_t do_count<MAX_X>() 
{ 
    return 0; 
} 

static constexpr const std::size_t COUNT = do_count(); 
0

se trouve que j'étais trop intelligent pour mon propre bien, il est aussi simple que cela:

#include <cstdint> 
#include <type_traits> 
#include <cstddef> 

struct unused_tag {}; 
struct used_tag {}; 

template<std::size_t X> 
struct traits { 
    using type = unused_tag; 
}; 

template<> 
struct traits<7> { 
    using type = used_tag; 
}; 

static constexpr const std::size_t MAX_COUNT = 10; 

template<std::size_t X = 0> 
constexpr std::size_t do_count() 
{ 
    if (std::is_same<typename traits<X>::type, unused_tag>::value) 
     return 0 + do_count<X + 1>(); 
    return 1 + do_count<X + 1>(); 
} 

template<> 
constexpr std::size_t do_count<MAX_COUNT>() 
{ 
    return 0; 
} 

static constexpr const std::size_t COUNT = do_count(); 

static_assert(COUNT == 1);