在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;
}
是否有任何机制允许这种行为,而无需直接了解任意模板类和任意类型? (像向 ArbitraryTemplateClass1 添加 typedef 来指定 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;
}