[英]specialization of template template paremeter of template class for nested template class
Normally you can partially specialize a template class against an instantiated template class. 通常,您可以针对实例化的模板类部分地专门化模板类。 For instance
例如
template<class T>
struct specialize_me {};
template<class T>
struct specialize_me<std::vector<T>> {
static const int foo = 3;
};
the template class specialize_me
is partially specialized against the instantiated template class std::vector<T>
. 模板类
specialize_me
部分专门针对实例化的模板类std::vector<T>
。 This specialization is selected when specialize_me
is instantiated with std::vector<T>
, for any class T
. 当选择这种专业化
specialize_me
与实例化std::vector<T>
对于任何类T
。
int main() {
std::cout << specialize_me<std::vector<int>>::foo; // Compiles.
}
However, I cannot figure out how to specialize a template template class against an instantiated nested template class: 但是,我无法弄清楚如何针对实例化的嵌套模板类专门化模板模板类:
// Nested template class.
template<class T>
struct Either {
template<class U>
struct Or {};
};
template<template<class> class T>
struct specialize_me_2 {};
template<class T>
struct specialize_me_2<Either<T>::template Or> {
static const int foo = 3;
};
In this case, the specialization is not selected when I instantiate specialize_me_2
with the class Either<T>::template Or
for any class T
. 在这种情况下,当我使用类
Either<T>::template Or
任何类T
实例化specialize_me_2
时, 不会选择特化。 My guess is that this happens because the compiler would have to confirm or deny, "There exists a T
such that Either<T>::template Or
is the same type as the specialize_me_2
instantiation" in order to select my specialization, and it is not programmed nor specified to do so. 我的猜测是,这是因为编译器必须确认或否认,“存在一个
T
,使得Either<T>::template Or
与specialize_me_2
实例化的类型相同”,以便选择我的专业化,它是没有编程也没有指定这样做。
int main() {
std::cout << specialize_me_2<Either<int>::Or>::foo; // Does not compile. 'foo' is not a member of specialize_me_2<Either<int>::Or>.
}
Is there a way to specialize specialize_me_2
such that the specialization is selected whenever specialize_me_2
is instantiated with Either<T>::Or
for any T
? 有没有办法专门化
specialize_me_2
这样只要specialize_me_2
使用Either<T>::Or
任何T
实例化,就会选择特化?
This Either
struct is eventually going to represent an error-carrying type, so Either<T>
denotes that T
is the error type, and Either<T>::Or<U>
denotes that U
is the type being carried by the successful computation. 这个
Either
结构最终将表示一个携带错误的类型,因此, Either<T>
表示T
是错误类型,并且Either<T>::Or<U>
表示U
是成功计算所携带的类型。
If this is impossible, I might still be able to use #define
s to enable you to define Either<T>
for each T
as it is needed, where #define
also includes the specialize_me_2
specialization for that particular Either<T>::Or
. 如果这是不可能的,我可能仍然可以使用
#define
来使你能够为每个T
定义Either<T>
,其中#define
还包括specialize_me_2
特殊化的特定Either<T>::Or
。 Indeed, I intend to use the Either
struct in programs by writing template<class T> using FooError = Either<Foo>::Or<T>
anyway and then write FooError<Bar>
, FooError<Quux>
and so on, so using this wouldn't be a huge break from the intended usage. 实际上,我打算通过
template<class T> using FooError = Either<Foo>::Or<T>
编写template<class T> using FooError = Either<Foo>::Or<T>
程序中的Either
结构,然后编写FooError<Bar>
, FooError<Quux>
等等,所以使用这不会是预期用途的巨大突破。
Intriguing problem. 有趣的问题。
To solve it without too much pain... if you can add new using
type inside Or
要解决它而不要太痛苦...如果你可以在
Or
里面添加新的using
类型
template <typename T>
struct Either
{
template <typename>
struct Or
{ using specialOrType = T; };
};
then you can add a second template parameter, a typename with void
as default, in specialize_me_2
然后你可以在
specialize_me_2
添加第二个模板参数,默认情况下为void
的typename
template <template <typename> class C, typename = void>
struct specialize_me_2
{ static const int foo = 2; };
and using SFINAE over specialOrType
并使用SFINAE而不是
specialOrType
template <typename ...>
using myVoidT = void;
template <template <typename> class C>
struct specialize_me_2<C, myVoidT<typename C<void>::specialOrType>>
{
using T = typename C<void>::specialOrType;
static const int foo = 3;
};
you get your working specialization. 你得到你的工作专业。
Instead of myVoidT
, starting from C++17, you can obviously use std::void_t
. 而不是
myVoidT
,从C ++ 17开始,显然可以使用std::void_t
。
Observe that this way you can't deduce the original T
type but you can recover it through specialOrType
. 请注意,这样您就无法推断出原始
T
类型,但您可以通过specialOrType
恢复它。
Observe also that this require (as pointed by aschepler) that Or<void>
is a valid specialization. 另请注意,这需要(如aschepler所指出的)
Or<void>
是一个有效的特化。 If this isn't the case, you should choose another type X
so that Or<X>
is a valid specialization for all Either<T>
. 如果不是这种情况,则应选择另一种类型
X
以便Or<X>
是所有Either<T>
。 Suppose that, by example, Or<int>
is a valid specialization for every Either<T>
, the specialization become 假设,通过示例,
Or<int>
是每个Either<T>
的有效特化,专业化变为
template <template <typename> class C>
struct specialize_me_2<C, myVoidT<typename C<int>::specialOrType>>
{
using T = typename C<int>::specialOrType;
static const int foo = 3;
};
The following is a full working example 以下是一个完整的工作示例
#include <iostream>
template <typename ...>
using myVoidT = void;
template <typename>
struct NoEither
{ };
template <typename T>
struct Either
{
template <typename>
struct Or
{ using specialOrType = T; };
};
template <template <typename> class C, typename = void>
struct specialize_me_2
{ static const int foo = 2; };
template <template <typename> class C>
struct specialize_me_2<C, myVoidT<typename C<void>::specialOrType>>
{
using T = typename C<void>::specialOrType;
static const int foo = 3;
};
int main ()
{
std::cout << specialize_me_2<NoEither>::foo << std::endl;
std::cout << specialize_me_2<Either<int>::template Or>::foo << std::endl;
}
Looks like T can't be deduced in your specialization from Either<T>::Or
, passing T
in as another template parameter appears to make it work, if that is any use too you.. 看起来T不能在您的专业化中推断出来自
Either<T>::Or
,传递T
in作为另一个模板参数似乎使其工作,如果这是任何使用你...
#include <iostream>
template<class T>
struct Either {
template<class U>
struct Or {};
};
template<typename U,template<class> class T>
struct specialize_me_2 {};
template<class T>
struct specialize_me_2<T,Either<T>::template Or> {
static const int foo = 3;
};
int main() {
std::cout << specialize_me_2<int,Either<int>::Or >::foo; // Does compile
}
Which could be made a bit cleaner with a nested type member in Either
so you use like, 在
Either
使用嵌套类型成员可以使其更清洁,所以你使用like,
using someEitherType = Either<int>;
...
specialize_me_2<someEitherType::type, someEitherType::Or>::foo
Or just specialize on Either directly for the first template parameter, 或者只是直接专注于第一个模板参数,
template<class T>
struct specialize_me_2<Either<T>,Either<T>::template Or> {
static const int foo = 3;
};
and just pass in 然后传入
specialize_me_2<someEitherType, someEitherType::Or>::foo
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.