feklee
feklee

Reputation: 7705

Template template parameter with typed parameters?

The following code does not compile. Is it even possible to pass an instance of Configuration<t, u> as a template parameter? (to profit from optimization of constant expressions)

API:

template <int t, bool u>
struct Configuration {
  static constexpr int commonValue = t;
  static constexpr bool debug = u;
};

template <
  template<int t, bool u> Configuration<t, u> &conf,
  int x
>
class A {
public:
  int doSomething() {
    if (conf.debug) { // Optimize away if false
      // ...
    }
    return x * conf.commonValue; // Optimize to e.g. 6 with `conf.commonValue` =
                                 // 3, `x` = 2
  }
};

The user of the API should be able to do:

int main() {
    static constexpr Configuration<3, false> conf;
    A<conf, 2> a;
    A<conf, 5> b;
    A<conf, 8> c;
    std::cout << a.doSomething() << std::endl; // 6 (evaluated at compile time!)
    std::cout << b.doSomething() << std::endl; // 15
    std::cout << c.doSomething() << std::endl; // 24
}

Upvotes: 1

Views: 95

Answers (1)

Holt
Holt

Reputation: 37661

Since the attributes of Configuration are static, you should use a template type parameter1:

template <class ConfT, int x>
class A {
public:
  int doSomething() {
    if (ConfT::debug) { // Optimize away if false

    }
    return x * ConfT::commonValue;
  }
};

And then:

// Alias (not required):
using conf = Configuration<3, false>;

A<conf, 2> a;
A<conf, 3> b;

If you want non-static members, I don't think this is doable pre-C++17 (without passing template parameters of Configuration to A), but in C++17 you could do1:

template <auto const& conf, int x>
class A {
public:
  int doSomething() {
    if (conf.debug) { // Optimize away if false
    }
    return x * conf.commonValue;
  }
};

But note that you can only pass references to variables with static storage duration.

1 In the first case, you can restrict the type to Configuration<...> by specializing A, in the second case, you can restrict the type of conf using an extra template parameter with std::enable_if.


You should also make the attributes constexpr in Configuration, not simply const:

template <int t, bool u>
struct Configuration {
  static constexpr int commonValue = t;
  static constexpr bool debug = u;
};

Upvotes: 3

Related Questions