C++ 嵌套模板结构
C++ nested templates structs
所以我对这样的代码有疑问:
我有这样的结构
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;
我的目标是创建“Outer
”结构,它采用 bool
或 Inner<int N>
并将 Outer::val
设置为 Inner::val
或 bool
所以我创建了这样的东西(不工作):
template <bool B>
struct Outer
{
enum
{
val = B
};
};
template <Inner<int> I>
struct Outer
{
enum
{
val = I::val
};
};
这有什么问题以及如何解决?
(我看过一些类似的问题,但仍然无法将其应用于我的问题)
您的代码中存在一些问题。
首先:你定义两个不同的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;
然后你可以为 Inner
类型定义一个 Outer
特化
template <int N>
struct Outer<Inner<N>>
{ enum { val = Inner<N>::val }; }; // or simply enum { val = N };
对于 bool
值,您必须将它们包装在 class 中;我建议(从 C++11 开始)使用标准 class 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_constant
(shorthand for std::integral_constant
for bool
values)
int b = Outer<std::bool_constant<false>>::val;
模板参数可以是类型、值(非类型)或模板 [temp.param]。您要实现的目标需要您的模板 Outer
具有可以是类型或值的参数。不幸的是,这是不可能的。
你可以做的是将你的 bool 值包装在一个类型中:
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
重命名为 value
,则可以使用标准库在 std::bool_constant
和 std::true_type
中提供的包装器,并且std::false_type
.
在 C++17 之前,非类型模板参数不能是 class 类型 [temp.param]/4, C++20 will lift this restriction and allow template parameters of any literal type。因此,只要 Inner
可以是文字类型,您就可以直接传递类型 Inner
的值并使用自动模板参数:
struct Inner
{
int N;
constexpr Inner(int N) : N(N) {}
constexpr operator int() const { return 2*N; }
};
template <auto val>
struct Outer
{
enum
{
value = val
};
};
auto a = Outer<Inner(4)>::value;
auto c = Outer<false>::value;
所以我对这样的代码有疑问:
我有这样的结构
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;
我的目标是创建“Outer
”结构,它采用 bool
或 Inner<int N>
并将 Outer::val
设置为 Inner::val
或 bool
所以我创建了这样的东西(不工作):
template <bool B>
struct Outer
{
enum
{
val = B
};
};
template <Inner<int> I>
struct Outer
{
enum
{
val = I::val
};
};
这有什么问题以及如何解决? (我看过一些类似的问题,但仍然无法将其应用于我的问题)
您的代码中存在一些问题。
首先:你定义两个不同的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;
然后你可以为 Inner
类型定义一个 Outer
特化
template <int N>
struct Outer<Inner<N>>
{ enum { val = Inner<N>::val }; }; // or simply enum { val = N };
对于 bool
值,您必须将它们包装在 class 中;我建议(从 C++11 开始)使用标准 class 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_constant
(shorthand for std::integral_constant
for bool
values)
int b = Outer<std::bool_constant<false>>::val;
模板参数可以是类型、值(非类型)或模板 [temp.param]。您要实现的目标需要您的模板 Outer
具有可以是类型或值的参数。不幸的是,这是不可能的。
你可以做的是将你的 bool 值包装在一个类型中:
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
重命名为 value
,则可以使用标准库在 std::bool_constant
和 std::true_type
中提供的包装器,并且std::false_type
.
在 C++17 之前,非类型模板参数不能是 class 类型 [temp.param]/4, C++20 will lift this restriction and allow template parameters of any literal type。因此,只要 Inner
可以是文字类型,您就可以直接传递类型 Inner
的值并使用自动模板参数:
struct Inner
{
int N;
constexpr Inner(int N) : N(N) {}
constexpr operator int() const { return 2*N; }
};
template <auto val>
struct Outer
{
enum
{
value = val
};
};
auto a = Outer<Inner(4)>::value;
auto c = Outer<false>::value;