Tay*_*lor 4 c++ templates partial-specialization template-templates
我有一个由模板模板类参数化的类,它具有静态成员函数:
template <template <typename> class F>
struct A {
static int foo();
};
Run Code Online (Sandbox Code Playgroud)
此类没有默认定义foo,必须专门针对不同类型.
我还有一个带有嵌套模板类的模板模板类参数化的另一个类:
template <template <typename> class F>
struct B {
template <typename T>
struct C {};
};
Run Code Online (Sandbox Code Playgroud)
我想C专门A用于任何模板模板类F,专门A不已:
template <template <typename> class F>
struct A<B<F>::template C> {
static int foo();
};
template <template <typename> class F>
int A<B<F>::template C>::foo() {
return A<F>::foo() / 2;
}
Run Code Online (Sandbox Code Playgroud)
所以,如果我有一个专门的课程A:
template <typename T>
struct E {};
template <>
int A<E>::foo() {
return 42;
}
Run Code Online (Sandbox Code Playgroud)
我希望能够使用这样的专业化(并返回21):
int bar() {
return A<B<E>::template C>::foo();
}
Run Code Online (Sandbox Code Playgroud)
但是,这无法链接 - 它找不到引用A<B<E>::C>::foo().
(请注意,所有这些都在一个文件中 - 这里的标题没有什么奇怪的事情发生)
似乎编译器正在尝试使用主模板A而不是特化,这意味着foo未定义.为什么在这种情况下不使用专门化?
template <template <typename> class F>
struct A {
static int foo();
};
template <template <typename> class F>
struct B {
template <typename T>
struct C {};
};
template <template <typename> class F>
struct A<B<F>::template C> {
static int foo();
};
template <template <typename> class F>
int A<B<F>::template C>::foo() {
return A<F>::foo() / 2;
}
template <typename T>
struct E {};
template <>
int A<E>::foo() {
return 42;
}
int bar() {
// Link fails - error: undefined reference to 'A<B<E>::C>::foo()'
return A<B<E>::template C>::foo();
}
Run Code Online (Sandbox Code Playgroud)
template<class T>
struct A {};
template<class T>
struct B {
using type=T;
};
template<class T>
struct A<typename B<T>::type> {};
Run Code Online (Sandbox Code Playgroud)
这基本相同,但模板层少1个.
这也不起作用.
问题在于,B<T>::type或者B<T>::template Z在一般情况下是任意编译时函数.
并且为了对它进行模式匹配,我们需要反转这个任意编译时函数.
标准说"编译器不必这样做",这是你可以在这里做的少数理智的事情之一.它绝对说明了类型; 对于模板,嗯,标准的模板模板参数的措辞往往缺少细节,所以如果缺少措辞,我不会感到惊讶.但如果没有,那将是标准中的一个错误.
为了从中走
template<class T>
struct A<typename B<T>::type> {};
Run Code Online (Sandbox Code Playgroud)
要查看是否A<foo>匹配它,它必须测试所有类型T以查看它们中的哪一个B<T>::type等于foo.
这可能不是你打算问的问题,但这就是你要求的.
您的模板示例也是如此.
template <template <typename> class F>
struct A<B<F>::template C> {
static int foo();
};
Run Code Online (Sandbox Code Playgroud)
你要求编译器检查每个类型F,如果你将它传递给任意模板B<>然后::C在其中进行评估,模板是否匹配你传递的内容A.
第一个有趣的案例
template<class X>
struct C0 {};
template <template <typename> class F>
struct B {
template <typename T>
using C=C0<X>:
};
Run Code Online (Sandbox Code Playgroud)
现在,是什么F在A<C0>?每个人都有F资格.
template<class X>
struct C0 {};
template <template <typename> class F, class=void>
struct B {
template <typename T>
using C=C0<X>:
};
template<class X>
struct C1 {};
template <template <typename> class F, class=void>
struct B<
F,
std::enable_if_t<
proves_collatz_conjecture( F<int>::value )
>
> {
template <typename T>
using C=C1<T>;
};
Run Code Online (Sandbox Code Playgroud)
现在要模式化A<C0>,编译器必须生成F这样F<int>::value一个编译时类型,在传递给编译时proves_collatz_conjecture返回true.
那将是有用的.
模板专业化是模式匹配.在C++中,您无法对依赖类型(以及可能是模板)进行模式匹配,因为类型和模板都没有超出其值的标识.
您无法检查定义变量,类型或模板的范围.因此您也无法模式匹配.
如果你想做你想做的事情,模板C本身就有一个你可以检查和测试的属性.
| 归档时间: |
|
| 查看次数: |
123 次 |
| 最近记录: |