【问题标题】:Extract first template parameter from a template template parameter and using it inside the class?从模板模板参数中提取第一个模板参数并在类中使用它?
【发布时间】:2021-05-02 03:37:20
【问题描述】:
我有以下问题:一个带有多个模板参数的类模板A,我想构建一个以A为模板参数的类B并提取A的第一个模板参数以便在某些方法中使用它(想想从 std::vector 中提取 int 并返回默认的 int{})。
#include <iostream>
template<typename... Ts>
struct A {};
template<template <typename InnerType> typename U> // <--- I'd like to use InnerType!
struct B {
InnerType foo() { return InnerType{}; }
};
int main()
{
B<A<int>> b;
std::cout << b.foo() << "\n";
return 0;
}
我知道这种幼稚的方式不会编译,但我不知道如何实现这样的目标。任何提示表示赞赏。
【问题讨论】:
标签:
c++
templates
variadic-templates
c++20
template-templates
【解决方案1】:
您不能直接命名模板模板参数的模板参数。尽管它看起来您可以命名它,但您注意到实际上不能使用该名称。
但是,您可以对采用单个模板参数的类型使用显式特化。
template<typename... Ts>
struct B; // incomplete type, only needed for specialization
template<template <typename> typename U, typename InnerType>
struct B<U<InnerType>> // specialized to be able to use InnerType
{
InnerType foo() { return InnerType{}; }
};
这是demo。
当然,您也可以通过为这些情况添加特化来对具有多个参数的模板执行类似的操作。
【解决方案2】:
没有InnerType。这是一个助记符。模板第一个参数的预期用途的文档。它是完全可选的。 B 的声明相当于
template<template <typename> typename U> // No name
struct B {
InnerType foo() { return InnerType{}; } // What now?
};
类模板不是类型。他们是生产类型的工厂。您不能向工厂查询将使用的参数,因为它还不知道。此外,您定义B 以接受模板作为参数,而实际上您打算为其提供类型。这是一个参数/参数不匹配的地方。
但是可以查询工厂的结果。如果您将B 的定义更改为接受类型而不是模板,那么您可以将其专门用于从模板创建的类型。这将使工厂和它使用的参数都可以推导出来。