2

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?

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42
  • It is not clear what you saying -- you need overloaded `get()` where `get()` return X bits while `get()` returns exactly one bit? – myaut Apr 10 '15 at 11:05
  • 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](http://coliru.stacked-crooked.com/a/f4fcbfcb0be3ba07) ? – Piotr Skotnicki Apr 10 '15 at 11:26
  • @myaut I want to overload get() so get() is valid and not just get() where the type of value is a template class. – Goswin von Brederlow Apr 10 '15 at 11:34
  • @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 value`. – Goswin von Brederlow Apr 10 '15 at 11:38
  • @GoswinvonBrederlow that's why I explained that it's not possible what you want – Piotr Skotnicki Apr 10 '15 at 11:40

1 Answers1

2

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
Barry
  • 286,269
  • 29
  • 621
  • 977
  • PiotrS already suggested that in the comments but that uses the type and not the value. I already have it working for types. I get that I can't use a non-type of BitValue but what about making it BitValue* or BitValue&? That should fit 4.2 and 4.3. What's the syntax for that? – Goswin von Brederlow Apr 10 '15 at 11:45
  • @GoswinvonBrederlow The syntax would be `template * bf> bool get() { .. }`, but then `bf` would have to have linkage. And you'd have to pass `N` in anyway - so it's a more restrictive, less usable solution than the one you started with. – Barry Apr 10 '15 at 11:59