作为非类型模板参数的类模板实例的语法

时间:2018-01-10 23:47:27

标签: c++ templates

即使在模板参数上读取cppreference之后,我也找不到正确的语法。以下内容无法编译,但希望能够描述我想要做的事情。什么是正确的语法?

template <class DisplayType>
class DisplayAdapter : public DisplayType
{

};

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

以下是它应该如何使用:

struct S{};

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

    return 0;
}

这是整个事情的Ideone片段:https://ideone.com/dvbYt8

3 个答案:

答案 0 :(得分:3)

您想要的不是模板模板参数。

模板模板参数用于传递模板,如下所示:

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

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

如您所见,您可以传递模板名称。请记住,模板不是类型,而是类型的蓝图,语言(和标准)不是以与类型相同的方式处理模板。

我假设您的示例尝试使用非类型模板参数?

非类型模板参数是模板参数,它是值而不是类型。它可以是任何整数类型,引用类型和指针类型。

例如,请查看std::array

std::array<int, 10> tenInts;

注意第二个参数是一个数字。这是因为std::array看起来像这样:

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

第二个参数是unsigned long int。

您还可以将引用和指针作为模板参数传递:

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

您甚至可以将指针传递给任何类型作为参考模板参数:

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

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

这似乎更接近你想要的。但是,您似乎有许多不同类型要作为模板参数发送,因为要传递的实例类型是模板化的。为此,您需要C ++ 17模板自动功能:

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

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

完成了!

如果您没有C ++ 17,请不要担心,只需将显示类型与您的实例一起传递(C ++ 14示例):

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

// Internal linkage
DisplayAdapter<S> da;

int main() {
    Painter<S, da> painter;
}

答案 1 :(得分:1)

如果它是像int这样的简单类型,你只需使用type而不是typename关键字,例如

template <int x>

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

但是你不能在这里放置任意类型的对象。

有关非类型模板参数的更多信息,请参阅another Q&A

答案 2 :(得分:0)

您需要在class

之前添加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