C ++嵌套模板结构

时间:2019-12-01 13:13:32

标签: c++ templates metaprogramming template-meta-programming template-specialization

所以我对这样的代码有疑问:

我有这样的结构

template <int N>
struct Inner
{
    enum
    {
        val = 2*N
    };
};

我想实现这样的目标:

int v = Outer<Inner<4>>::val;
int b = Outer<false>::val;
cout<< v <<endl;
cout<< b <<endl;

我的目标是创建一个采用Outerbool的“ Inner<int N>”结构,并将Outer::val设置为Inner::valbool 所以我创建了这样的东西(不起作用):

template <bool B>
struct Outer
{
    enum
    {
        val = B
    };
};

template <Inner<int> I>
struct Outer
{
    enum
    {
        val = I::val
    };
};

这有什么问题,以及如何解决? (我见过类似的问题,但仍然无法将其应用于我的问题)

2 个答案:

答案 0 :(得分:2)

您的代码中存在一些问题。

首先:您定义两个不同的Outer结构

template <bool B>
struct Outer
 { /* ... */ };

template <Inner<int> I>
struct Outer
 { /* ... */ };

你不能。

如果需要,可以声明一个Outer结构和两个专业化,但是必须确定必须接收哪种类型的模板参数Outer

因为,看着你的渴望,

int v = Outer<Inner<4>>::val;
int b = Outer<false>::val;

您想在一种情况下将类型传递给它(Inner<4>,在另一种情况下将值传递给它。而且你不能。

您必须确定Outer是否接收类型或值。在C ++ 17之前,如果要接收值,则必须确定值的类型;从C ++ 17开始,您可以声明Outer接收通用类型的值(auto作为值的类型)。

问题:Inner<int>的值不能作为模板参数(但另请参见Michael Kenzel的答案,该答案显示了基于模板值参数的C ++ 20解决方案)。

因此,我看到的唯一解决方案(在C ++ 20之前)是声明Outer为接收类型

template <typename>
struct Outer;

然后,您可以为Outer类型定义Inner专业化

template <int N>
struct Outer<Inner<N>>
 { enum { val = Inner<N>::val }; }; // or simply enum { val = N };

对于bool值,您必须将它们包装在一个类中;我建议(从C ++ 11开始)使用标准类std::integral_constant和以下Outer专业化的定义

template <bool B>
struct Outer<std::integral_constant<bool, B>>
 { enum { val = B }; };

用途如下

int v = Outer<Inner<4>>::val;
int b = Outer<std::integral_constant<bool, false>>::val;

std::cout << v << std::endl;
std::cout << b << std::endl;

您还可以使用std::false_type定义b

int b = Outer<std::false_type>::val;

并且从C ++ 17开始,也是std::bool_constantstd::integral_constantbool值的简写)

int b = Outer<std::bool_constant<false>>::val;

答案 1 :(得分:2)

模板参数可以是类型,值(非类型)或模板[temp.param]。您要实现的目标要求模板 substring 012345 0 012345 substring 012345 1 12345 substring 012345 2 2345 substring 012345 3 345 substring 012345 4 45 substring 012345 5 5 substring 012345 6 substring 012345 3 5 345 substring 012345 3 4 34 substring 012345 2 4 234 substring 012345 1 3 123 具有一个可以是类型或值的参数。不幸的是,这是不可能的。

您可以做的是将bool值包装为以下类型:

Outer

,然后为template <bool b> struct InnerBoolean { static constexpr bool val = b; };

定义一个通用定义
Outer

,然后使用template <typename T> struct Outer { enum { value = T::val }; }; Outer<Inner<4>>

如果您将Outer<InnerBoolean<False>>重命名为val,则无需编写自己的包装器,而是可以使用标准库在std::bool_constantvalue和{{ 1}}。

在C ++ 17之前的版本中,非类型模板参数不能为类类型[temp.param]/4,而C ++ 20将取消此限制,并允许任何literal type模板参数。因此,只要std::true_type可以是文字类型,您就可以直接传递类型为std::false_type的值并使用自动模板参数:

Inner