简体   繁体   中英

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

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

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;
}

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

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 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM