Home Syntax for an instance of a class template as a non-type template parameter
Reply: 3

Syntax for an instance of a class template as a non-type template parameter

Violet Giraffe
1#
Violet Giraffe Published in 2018-01-10 23:47:26Z

I can't find the right syntax even after reading cppreference on template params. The following doesn't compile, but hopefully describes what I want to do. What's the correct syntax?

template <class DisplayType>
class DisplayAdapter : public DisplayType
{

};

template<template <typename> DisplayAdapter>
class Painter // Takes an instance of DisplayAdapter, not a type!
{
}

Here is how it's supposed to be used:

struct S{};

int main()
{
    DisplayAdapter<S> concreteAdapter;
    Painter<concreteAdapter> p;

    return 0;
}

Here's Ideone snippet for the whole thing: https://ideone.com/dvbYt8

Guillaume Racicot
2#
Guillaume Racicot Reply to 2018-01-11 06:59:11Z

What you're wanting is not a template template parameter.

A template template parameter is used to pass templates around, like this:

template<template<typename> typename Container>
struct foo {
    Container<int> container;
};

int main() {
    foo<std::vector> f;
}

As you can see, you can pass template names around with that. Remember that templates are not types, but a blueprint for type, and the language (and the standard) is not treating templates the same way as types.


I assume with your examples your trying to use non-type template parameters?

A non-type template parameter is a template parameter that is a value instead of a type. It can be of any integral types, reference type and pointer type.

For example, look at std::array:

std::array<int, 10> tenInts;

Notice the second parameter is a number. This is because std::array look something like this:

template<typename T, std::size_t N>
struct array { /* ... */ };

The second parameter is an unsigned long int.

You can also pass references and pointers as template parameter:

template<int& i> struct foo {};
template<int* i> struct bar {};

int main() {
    // Need at least internal linkage in C++14 and older
    // No linkage required since C++17, only static needed.
    static int num = 0;

    foo<num> f;
    bar<&num> b;
}

You can even pass a pointer to any type as reference template parameter:

struct stuff {};
template<stuff& s> struct foo;

int main() {
    static stuff s{};
    foo<s> f; // works!
}

This seem to be closer to what you wanted. However, you seem to have many many different type you want to send as template parameter, as the type of the instances you want to pass around are templated. For that you'll need C++17 template auto feature:

template<auto& da>
struct Painter {
    // ...
};

int main() {
    static DisplayAdapter<S> concreteAdapter;
    Painter<concreteAdapter> p;
}

And done!

If you don't have C++17 with you don't worry, and simply pass the display type along with your instance (C++14 example):

template<typename DT, DisplayAdapter<DT>& da>
struct Painter {};

// Internal linkage
DisplayAdapter<S> da;

int main() {
    Painter<S, da> painter;
}
balki
3#
balki Reply to 2018-01-10 23:59:28Z

You need to add class before DisplayAdater

template <class DisplayType>
class DisplayAdapter : public DisplayType
{

};

template<template <typename> class DisplayAdapter>
class Painter // Takes an instance of DisplayAdapter, not a type!
{
};

https://godbolt.org/g/mV7YRC

RiaD
4#
RiaD Reply to 2018-01-11 06:34:44Z

If it was some simple type like int you would just use type instead of typename keyword e.g

template <int x>

or

template <std::vector<int>::value_type x>

But you can't put object of arbitrary type here.

More about non-type template parameters can be found in another Q&A

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.55518 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO