I have a database of objects and would like to count how many are of a particular type at compile time, but I'm having a bit of trouble getting this to compile.
Here's a cut down example of what I've been trying so far, but this fails to compile with "error: call to function 'do_count' that is neither visible in the template definition nor found by argument-dependent lookup"
Is there a better way?
#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();
It seems like you found a different solution to your problem but here is a solution using std::enable_if if you were curious.
The problem is that the call of do_count from the !std::is_same<...> version cannot see the std::is_same<...> version so, as your compiler said, it is not visible from the call site and can't be resolved. To fix this, just make a forward declaration of the std::is_same<...>.
For your example, the following compiles for me: