1
votes

I'm trying to use a non-type template parameter which type is a template instance like this:

template<size_t num> class BitValue { ... };
class Foo {
  // works
  template<template<size_t> class BitValue, size_t num>
  bool get(BitValue<num> && t) { ... }

  // fails
  template<typename T> bool
  template<Bitvalue<num> bit> bool get() { ... };
  template<template <size_t> Bitvalue bit> bool get() { ... };
  template<template <size_t> class Bitvalue bit> bool get() { ... };
  template<template <size_t> BitValue, size_t num, Bitvalue<num> bit> bool get() { ... };
};

You might say: Why not use the foo.get(value)? Foo represents a kind of bitfield that has multi-bit values and single-big values. I want foo.get<...>() for all members of the bitfield for consistency.

Why not use `foo.get<typeof(value)>'? foo.get<MultiBitType>() returns the value of the multi-bit field. foo.get<SingleBitType>() returns the raw value of the single-bit type. But unfortunately some of the bits are negated. So foo.get<NegatedValue>() should return !foo.get<typeof(NegatedValue)>().

Any ideas if it is possible to have a template non-type template parameter at all? And if so how?

1
It is not clear what you saying -- you need overloaded get() where get<X>() return X bits while get() returns exactly one bit?myaut
you neither can infer the type of non-type template argument, nor you can use an instance of a custom class as a non-type template argument. did you mean this ?Piotr Skotnicki
@myaut I want to overload get() so get<value>() is valid and not just get<Type>() where the type of value is a template class.Goswin von Brederlow
@PiotrS. No. You are using a type. It's not just the bit position num that is important but get() also needs the value of BitValue<num> value.Goswin von Brederlow
@GoswinvonBrederlow that's why I explained that it's not possible what you wantPiotr Skotnicki

1 Answers

2
votes

It is impossible to have a non-type template parameter of type BitValue<size_t> since the allowed types are [temp.param]:

A non-type template-parameter shall have one of the following (optionally cv-qualified) types:

(4.1) — integral or enumeration type,
(4.2) — pointer to object or pointer to function,
(4.3) — lvalue reference to object or lvalue reference to function,
(4.4) — pointer to member,
(4.5) — std::nullptr_t.

But you can just template on any type and delegate to a metafunction:

template <typename T>
bool get() {
    size_t bit = bit_number<T>::value;
    ...
}

where:

template <typename T> struct bit_number;
template <size_t N>
struct bit_number<BitValue<N>> : std::integral_constant<size_t, N> { };
// other specializations