2016-12-22 2 views
1

У меня есть база данных объектов и хотелось бы подсчитать, сколько из них имеет определенный тип во время компиляции, но у меня возникают проблемы с его компиляцией.Как выполнить подсчет constexpr на основе черта типа

Вот приведенный ниже пример того, что я пытался до сих пор, но это не удается скомпилировать с помощью «error: call to function do_count», который не является ни видимым в определении шаблона, ни найденным зависящим от аргумента поиска »,

Есть ли лучший способ?

#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

Что это «база данных» выглядит? Можете ли вы дать более подробное объяснение примерам желаемого ввода и вывода? В какой строке это ошибка? – qxz

ответ

0

Похоже, вы нашли другое решение проблемы, но здесь это решение, использующее std :: enable_if, если вам было интересно.

Проблема заключается в том, что вызов do_count из версии! Std :: is_same < ...> не может видеть версию std :: is_same < ...>, поэтому, как сказал ваш компилятор, это не видно из сайт вызова и не может быть разрешен. Чтобы исправить это, просто сделайте прямое объявление std :: is_same < ...>.

Для примера, следующий компилирует для меня:

#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

Оказывается, я был слишком умен для своего собственного блага, это так просто, как это:

#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); 
Смежные вопросы