模板元编程递归评估
Template metaprogramming recursive evaluation
template<typename T>
struct rm_const_volatile {
using type = T;
};
// Call this (partial)specialization as "1"
template<typename T>
struct rm_const_volatile<const T> {
// remove topmost const and recurse on T
using type = typename rm_const_volatile<T>::type;
};
// Call this (partial)specialization as "2"
template<typename T>
struct rm_const_volatile<volatile T> {
// remove topmost volatile and recurse on T
using type = typename rm_const_volatile<T>::type;
};
我已经像上面那样定义了 remove const volatile 限定符模板元程序。
逻辑上,当我写 rm_const_volatile<const volatile int>
时,我的期望是编译器将按以下顺序计算:
案例一:
rm_const_volatile<const volatile int>
- [使用专精 1]->
rm_const_volatile<volatile int>
- [使用专精 2]->
rm_const_volatile<int>
- [使用通用模板]->
int
(最终结果).
案例二:
rm_const_volatile<volatile const int>
- [使用专精 2]->
rm_const_volatile<const int>
- [使用专精 1]->
rm_const_volatile<int>
- [使用通用模板]->
int
(最终结果).
所以在我看来,上面的模板专业化和通用定义足以删除任何 const volatile 限定符。
将实际行为错误删除为模棱两可的模板实例化。
// In main() below two calls are present (refer cpp.sh link below mentioned for full code)
----
std::cout << "Is volatile const int integral type with rm_const_volatile: " << is_integral<rm_const_volatile<volatile const int>::type>::value << std::endl;
std::cout << "Is const volatile int integral type with rm_const_volatile: " << is_integral<rm_const_volatile<const volatile int>::type>::value << std::endl;
-------
In function 'int main()':
54:132: error: ambiguous class template instantiation for 'struct rm_const_volatile<const volatile int>'
26:8: error: candidates are: struct rm_const_volatile<const T>
31:8: error: struct rm_const_volatile<volatile T>
54:95: error: incomplete type 'rm_const_volatile<const volatile int>' used in nested name specifier
54:95: error: incomplete type 'rm_const_volatile<const volatile int>' used in nested name specifier
54:138: error: template argument 1 is invalid
当我添加以下模板专业化时,一切正常。
template<typename T>
struct rm_const_volatile<const volatile T> {
using type = T;
};
完整代码请参考此link。
我想知道为什么编译器将模板实例化报告为不明确,而显然它可以切断最顶层的限定符并递归实例化为最终结果,正如我在上面的案例 1 和 2 中提到的那样。
非常感谢您的宝贵意见,并衷心感谢您的宝贵时间。
I would like to know why the compiler reports template instantiation as ambiguous
C++ 认为 const volatile int
和 volatile const int
是同一类型。它们可以互换并且意思相同。
这种类型的一些其他拼写方式:
int const volatile
int volatile const
const int volatile
volatile int const
也就是说,C++ 永远不会根据您选择拼写特定类型的方式更改重载规则。
因此,模板特化 <const T>
和 <volatile T>
都同样专用于 <const volatile int>
。两个限定词都不优先于另一个。
template<typename T>
struct rm_const_volatile {
using type = T;
};
// Call this (partial)specialization as "1"
template<typename T>
struct rm_const_volatile<const T> {
// remove topmost const and recurse on T
using type = typename rm_const_volatile<T>::type;
};
// Call this (partial)specialization as "2"
template<typename T>
struct rm_const_volatile<volatile T> {
// remove topmost volatile and recurse on T
using type = typename rm_const_volatile<T>::type;
};
我已经像上面那样定义了 remove const volatile 限定符模板元程序。
逻辑上,当我写 rm_const_volatile<const volatile int>
时,我的期望是编译器将按以下顺序计算:
案例一:
rm_const_volatile<const volatile int>
- [使用专精 1]->
rm_const_volatile<volatile int>
- [使用专精 2]->
rm_const_volatile<int>
- [使用通用模板]->
int
(最终结果).
案例二:
rm_const_volatile<volatile const int>
- [使用专精 2]->
rm_const_volatile<const int>
- [使用专精 1]->
rm_const_volatile<int>
- [使用通用模板]->
int
(最终结果).
所以在我看来,上面的模板专业化和通用定义足以删除任何 const volatile 限定符。
将实际行为错误删除为模棱两可的模板实例化。
// In main() below two calls are present (refer cpp.sh link below mentioned for full code)
----
std::cout << "Is volatile const int integral type with rm_const_volatile: " << is_integral<rm_const_volatile<volatile const int>::type>::value << std::endl;
std::cout << "Is const volatile int integral type with rm_const_volatile: " << is_integral<rm_const_volatile<const volatile int>::type>::value << std::endl;
-------
In function 'int main()':
54:132: error: ambiguous class template instantiation for 'struct rm_const_volatile<const volatile int>'
26:8: error: candidates are: struct rm_const_volatile<const T>
31:8: error: struct rm_const_volatile<volatile T>
54:95: error: incomplete type 'rm_const_volatile<const volatile int>' used in nested name specifier
54:95: error: incomplete type 'rm_const_volatile<const volatile int>' used in nested name specifier
54:138: error: template argument 1 is invalid
当我添加以下模板专业化时,一切正常。
template<typename T>
struct rm_const_volatile<const volatile T> {
using type = T;
};
完整代码请参考此link。
我想知道为什么编译器将模板实例化报告为不明确,而显然它可以切断最顶层的限定符并递归实例化为最终结果,正如我在上面的案例 1 和 2 中提到的那样。
非常感谢您的宝贵意见,并衷心感谢您的宝贵时间。
I would like to know why the compiler reports template instantiation as ambiguous
C++ 认为 const volatile int
和 volatile const int
是同一类型。它们可以互换并且意思相同。
这种类型的一些其他拼写方式:
int const volatile
int volatile const
const int volatile
volatile int const
也就是说,C++ 永远不会根据您选择拼写特定类型的方式更改重载规则。
因此,模板特化 <const T>
和 <volatile T>
都同样专用于 <const volatile int>
。两个限定词都不优先于另一个。