模板 class 的模板模板参数对嵌套模板 class 的特化
specialization of template template paremeter of template class for nested template class
通常您可以针对实例化模板 class 部分特化模板 class。例如
template<class T>
struct specialize_me {};
template<class T>
struct specialize_me<std::vector<T>> {
static const int foo = 3;
};
模板 class specialize_me
部分专门针对实例化模板 class std::vector<T>
。当使用 std::vector<T>
实例化 specialize_me
时,对于任何 class T
.
,此特化是 selected
int main() {
std::cout << specialize_me<std::vector<int>>::foo; // Compiles.
}
但是,我不知道如何针对实例化的嵌套模板 class:
专门化模板模板 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;
};
在这种情况下,当我用 class Either<T>::template Or
实例化 specialize_me_2
时,特化是 而不是 selected任何 class T
。我的猜测是,发生这种情况是因为编译器必须确认或拒绝 "There exists a T
such that Either<T>::template Or
is the same type as the specialize_me_2
instantiation" 才能 select 我的专业化,而且它没有被编程也没有指定这样做。
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>.
}
有没有一种方法可以专门化 specialize_me_2
,以便在 specialize_me_2
为任何 T
用 Either<T>::Or
实例化时 selected 专门化?
这个Either
结构最终将表示一个错误类型,所以Either<T>
表示T
是错误类型,Either<T>::Or<U>
表示U
是计算成功携带的类型。
如果这不可能,我可能仍然可以使用 #define
s 使您能够根据需要为每个 T
定义 Either<T>
,其中 #define
还包括针对特定 Either<T>::Or
的 specialize_me_2
专业化。事实上,我打算通过编写 template<class T> using FooError = Either<Foo>::Or<T>
在程序中使用 Either
结构,然后编写 FooError<Bar>
、FooError<Quux>
等等,所以使用它不会是一个巨大的偏离预期用途。
看起来 T 无法从 Either<T>::Or
中推导出您的专业化,将 T
作为另一个模板参数传入似乎可以使它工作,如果这对您也有用..
#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
}
在 Either
中使用嵌套类型成员可以使它更清晰一些,因此您可以使用 like,
using someEitherType = Either<int>;
...
specialize_me_2<someEitherType::type, someEitherType::Or>::foo
或者直接针对第一个模板参数专注于 Either,
template<class T>
struct specialize_me_2<Either<T>,Either<T>::template Or> {
static const int foo = 3;
};
然后传入
specialize_me_2<someEitherType, someEitherType::Or>::foo
有趣的问题。
轻松解决它...如果您可以在 Or
中添加新的 using
类型
template <typename T>
struct Either
{
template <typename>
struct Or
{ using specialOrType = T; };
};
然后你可以添加第二个模板参数,默认为 void
的类型名,在 specialize_me_2
template <template <typename> class C, typename = void>
struct specialize_me_2
{ static const int foo = 2; };
并在 specialOrType
上使用 SFINAE
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;
};
您获得工作专业化。
而不是myVoidT
,从C++17开始,你显然可以使用std::void_t
.
观察到这样你不能推导出原来的T
类型但是你可以通过specialOrType
.
恢复它
还请注意,这需要(正如 aschepler 所指出的那样)Or<void>
是一个有效的专业化。如果不是这种情况,您应该选择另一种类型 X
,以便 Or<X>
是所有 Either<T>
的有效特化。例如,假设 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;
};
以下是一个完整的工作示例
#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;
}
通常您可以针对实例化模板 class 部分特化模板 class。例如
template<class T>
struct specialize_me {};
template<class T>
struct specialize_me<std::vector<T>> {
static const int foo = 3;
};
模板 class specialize_me
部分专门针对实例化模板 class std::vector<T>
。当使用 std::vector<T>
实例化 specialize_me
时,对于任何 class T
.
int main() {
std::cout << specialize_me<std::vector<int>>::foo; // Compiles.
}
但是,我不知道如何针对实例化的嵌套模板 class:
专门化模板模板 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;
};
在这种情况下,当我用 class Either<T>::template Or
实例化 specialize_me_2
时,特化是 而不是 selected任何 class T
。我的猜测是,发生这种情况是因为编译器必须确认或拒绝 "There exists a T
such that Either<T>::template Or
is the same type as the specialize_me_2
instantiation" 才能 select 我的专业化,而且它没有被编程也没有指定这样做。
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>.
}
有没有一种方法可以专门化 specialize_me_2
,以便在 specialize_me_2
为任何 T
用 Either<T>::Or
实例化时 selected 专门化?
这个Either
结构最终将表示一个错误类型,所以Either<T>
表示T
是错误类型,Either<T>::Or<U>
表示U
是计算成功携带的类型。
如果这不可能,我可能仍然可以使用 #define
s 使您能够根据需要为每个 T
定义 Either<T>
,其中 #define
还包括针对特定 Either<T>::Or
的 specialize_me_2
专业化。事实上,我打算通过编写 template<class T> using FooError = Either<Foo>::Or<T>
在程序中使用 Either
结构,然后编写 FooError<Bar>
、FooError<Quux>
等等,所以使用它不会是一个巨大的偏离预期用途。
看起来 T 无法从 Either<T>::Or
中推导出您的专业化,将 T
作为另一个模板参数传入似乎可以使它工作,如果这对您也有用..
#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
}
在 Either
中使用嵌套类型成员可以使它更清晰一些,因此您可以使用 like,
using someEitherType = Either<int>;
...
specialize_me_2<someEitherType::type, someEitherType::Or>::foo
或者直接针对第一个模板参数专注于 Either,
template<class T>
struct specialize_me_2<Either<T>,Either<T>::template Or> {
static const int foo = 3;
};
然后传入
specialize_me_2<someEitherType, someEitherType::Or>::foo
有趣的问题。
轻松解决它...如果您可以在 Or
using
类型
template <typename T>
struct Either
{
template <typename>
struct Or
{ using specialOrType = T; };
};
然后你可以添加第二个模板参数,默认为 void
的类型名,在 specialize_me_2
template <template <typename> class C, typename = void>
struct specialize_me_2
{ static const int foo = 2; };
并在 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;
};
您获得工作专业化。
而不是myVoidT
,从C++17开始,你显然可以使用std::void_t
.
观察到这样你不能推导出原来的T
类型但是你可以通过specialOrType
.
还请注意,这需要(正如 aschepler 所指出的那样)Or<void>
是一个有效的专业化。如果不是这种情况,您应该选择另一种类型 X
,以便 Or<X>
是所有 Either<T>
的有效特化。例如,假设 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;
};
以下是一个完整的工作示例
#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;
}