提问人:js87 提问时间:11/5/2023 最后编辑:cigienjs87 更新时间:11/5/2023 访问量:50
在两个本身就是模板的模板类型参数之间强制执行通用模板类型参数
Enforcing a common template type parameter among two template type parameters that are themselves templates
问:
在 C++ 中,有没有办法确保两个或多个模板类型参数本身就是具有通用模板类型参数的模板类型?
假设我有这个:
struct ArbitraryType {};
template <typename T>
class ArbitraryTemplateClass1 {
/* ... */
};
template <typename T>
class ArbitraryTemplateClass2 {
/* ... */
};
我想要一个可以接受 和 作为模板类型参数的模板,但要确保它们都有一个通用的模板类型参数(然后对该类型做一些事情)。例如,我希望能够执行以下操作:ArbitraryTemplateClass1
ArbitraryTemplateClass2
T
T
template <typename U <typename T>, typename V<T>> // desired (but incorrect) syntax
struct CommonTemplateTypeParameterProducer {
T Produce() { return T(); }
};
// Which would allow this:
int main() {
CommonTemplateTypeParameterProducer<ArbitraryTemplateClass1<ArbitraryType>,
ArbitraryTemplateClass2<ArbitraryType>> producer;
// Type of t should be ArbitraryType
auto t = producer.Produce();
// This should fail to instantiate CommonTemplateTypeParameterProducer because U and V don't share a common T
//CommonTemplateTypeParameterProducer<ArbitraryTemplateClass1<ArbitraryType>,
// ArbitraryTemplateClass2<int>> producer2;
}
是否有任何机制允许这种行为,而无需直接了解任意模板类和任意类型?(例如添加一个 typedef 来指定 的类型 不会是一个选项)。如果可能的话,我还想避免添加第三个模板类型参数,理想情况下,我希望模板能够推断出它正在强制执行的通用类型。ArbitraryTemplateClass1
T
CommonTemplateTypeParameterProducer;
注意:像这样的东西也有助于确保两个模板类型参数(也是可变参数模板)都具有相同的模板参数。
我已经研究了C++的概念/约束/要求和模板模板参数,但到目前为止,似乎没有一个能为这个特定问题提供解决方案。
答:
这是可能的,但可能不是最好的设计,因为如果有人需要添加另一个模板参数,一切都会中断。或者,如果您决定制作一个未模板化的版本,并且仅适用于一种特定类型。ArbitraryTemplateClass1
最好添加类似 / 的内容,并在模板中检查它,而不是实际的模板参数。 不应对其模板参数的模板参数进行监管。using type = T;
ArbitraryTemplateClass1
2
CommonTemplateTypeParameterProducer
#include <concepts>
template <typename T>
struct A
{
using type = T;
};
template <typename T>
struct B
{
using type = T;
};
template <typename X, typename Y>
requires std::same_as<typename X::type, typename Y::type>
struct Foo
{
X x;
Y y;
};
int main()
{
Foo<A<int>, B<int>> foo;
}
这是另一种选择。它与你提出的设计有同样的问题,但至少你不需要拼写两次模板参数:
template <typename T>
struct A {};
template <typename T>
struct B {};
template <
template <typename> typename X,
template <typename> typename Y,
typename T
>
struct Foo
{
X<T> x;
Y<T> y;
};
int main()
{
Foo<A, B, int> foo;
}
最后,这正是你所要求的。我添加了一个帮助程序模板,用于从任意模板中提取模板参数。这同样存在我上面描述的问题,并且还需要拼写两次模板参数。
#include <concepts>
template <typename T>
struct GetTemplateArgument {};
template <template <typename> typename T, typename U>
struct GetTemplateArgument<T<U>> {using type = U;};
template <typename T>
struct A {};
template <typename T>
struct B {};
template <typename X, typename Y>
requires std::same_as<typename GetTemplateArgument<X>::type, typename GetTemplateArgument<Y>::type>
struct Foo
{
X x;
Y y;
};
int main()
{
Foo<A<int>, B<int>> foo;
}
评论
ArbitraryTemplateClass1
ArbitraryTemplateClass1
您可以使用符合要求的部分专业化来执行此操作。
使用采用 2 个类型参数的主类。不要定义它,因此如果您尝试使用它,则会出现错误:
template <typename, typename>
struct CommonTemplateTypeParameterProducer;
然后编写一个部分专用化,它接受 2 个模板参数和 ,以及 1 个类型参数。如果变量声明中使用的类型与模式匹配,并且将选择此专用化:A
B
T
A<T>
B<T>
template <template <typename> typename A,
template <typename> typename B,
typename T>
struct CommonTemplateTypeParameterProducer<A<T>, B<T>>
{
T Produce() { return T(); }
};
这是一个演示。
评论
ArbitraryTemplateClass1<ArbitraryType>
不是一个模板,而是一个类型。CommonTemplateTypeParameterProducer<ArbitraryTemplateClass1, ArbitraryTemplateClass2<ArbitraryType>>