jca*_*er2 5 c++ templates template-specialization
通常,您可以针对实例化的模板类部分地专门化模板类.例如
template<class T>
struct specialize_me {};
template<class T>
struct specialize_me<std::vector<T>> {
static const int foo = 3;
};
Run Code Online (Sandbox Code Playgroud)
模板类specialize_me部分专门针对实例化的模板类std::vector<T>.对于任何类,在specialize_me实例化时选择此特化.std::vector<T>T
int main() {
std::cout << specialize_me<std::vector<int>>::foo; // Compiles.
}
Run Code Online (Sandbox Code Playgroud)
但是,我无法弄清楚如何针对实例化的嵌套模板类专门化模板模板类:
// 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;
};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,当我使用任何类的类实例化时,不会选择特化.我的猜测是,这是因为编译器将不得不证实或否认,"目前存在这样相同类型的实例化",以便选择我的专业化,它没有被编程也没有规定这样做.specialize_me_2Either<T>::template OrTTEither<T>::template Orspecialize_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>.
}
Run Code Online (Sandbox Code Playgroud)
是否有一种专门化的方法,以便在任何实例化specialize_me_2时specialize_me_2都选择专门化?Either<T>::OrT
这个Either结构最终将表示一个携带错误的类型,因此Either<T>表示它T是错误类型,并Either<T>::Or<U>表示这U是成功计算所携带的类型.
如果这是不可能的,我仍然可以使用#defines来使您能够根据需要定义Either<T>每个T,其中#define还包括该specialize_me_2特定的特化Either<T>::Or.实际上,我打算Either在程序中使用结构template<class T> using FooError = Either<Foo>::Or<T>,然后通过编写然后编写FooError<Bar>,FooError<Quux>等等,因此使用它不会与预期的用法有很大的差别.
有趣的问题。
为了解决这个问题而不会太痛苦......如果你可以using在里面添加新类型Or
template <typename T>
struct Either
{
template <typename>
struct Or
{ using specialOrType = T; };
};
Run Code Online (Sandbox Code Playgroud)
然后您可以添加第二个模板参数,void默认类型名称为specialize_me_2
template <template <typename> class C, typename = void>
struct specialize_me_2
{ static const int foo = 2; };
Run Code Online (Sandbox Code Playgroud)
并使用 SFINAEspecialOrType
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;
};
Run Code Online (Sandbox Code Playgroud)
你得到你的工作专业。
从 C++17开始myVoidT,您显然可以使用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;
};
Run Code Online (Sandbox Code Playgroud)
以下是一个完整的工作示例
#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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
158 次 |
| 最近记录: |