编译时的质因数列表:专用化错误
List of prime factors at compile-time: specialization error
考虑以下代码(链接到IDEONE):
#include <iostream>
#include <type_traits>
// List of factors
template<std::intmax_t ... Misc>
struct factors { };
// Declaration
template<std::intmax_t ... Misc>
struct factorization;
// Initial specialization
template<std::intmax_t Value>
struct factorization<Value>
{
typedef typename std::conditional<Value % 2 == 0,
typename factorization<Value / 2, 2, 2>::type,
typename factorization<Value / 2, 2 + 1>::type>::type type;
};
// Initial specialization when the value is not divisible by 2
template<std::intmax_t Value, std::intmax_t Divisor>
struct factorization<Value, Divisor>
{
typedef typename std::conditional<Value % Divisor == 0,
typename factorization<Value / Divisor, Divisor, Divisor>::type,
typename factorization<Value / Divisor, Divisor + 1>::type>::type type;
};
// Specialization after the first recusion step
template<std::intmax_t Value, std::intmax_t Divisor, std::intmax_t Prime>
struct factorization<Value, Divisor, Prime>
{
typedef typename std::conditional<Value % Divisor == 0,
typename factorization<Value / Divisor, Divisor, Divisor>::type,
typename factorization<Value / Divisor, Divisor + 1>::type>::type type;
};
// Recursion specialization
template<std::intmax_t Value, std::intmax_t Divisor, std::intmax_t Prime, std::intmax_t ... Primes>
struct factorization<Value, Divisor, Prime, Primes...>
{
typedef typename std::conditional<Value % Divisor == 0 && Divisor != Prime,
typename factorization<Value / Divisor, Divisor, Divisor, Prime,
Primes...>::type,
typename factorization<
Value % Divisor == 0 ? Value / Divisor : Value,
Divisor + (Value % Divisor != 0), Prime, Primes...>::type>::type type;
};
// Last recursion step
template<std::intmax_t Value, std::intmax_t ... Primes>
struct factorization<Value, Value, Primes...>
{
typedef typename factorization<1, Value, Value, Primes...>::type type;
};
// Finalize
template<std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization<1, Divisor, Primes...>
{
typedef factors<Primes...> type;
};
// Main
int main() {
typename factorization<18>::type x;
return 0;
}
此代码应列出一个数字的质因数,不重复:例如,factorization<18>::type
应等于factors<2, 3>
但它失败并显示以下错误:
prog.cpp: In instantiation of ‘struct factorization<4ll, 2ll, 2ll>’:
prog.cpp:36:79: required from ‘struct factorization<9ll, 2ll, 2ll>’
prog.cpp:18:67: required from ‘struct factorization<18ll>’
prog.cpp:67:28: required from here
prog.cpp:36:79: error: ambiguous class template instantiation for ‘struct factorization<2ll, 2ll, 2ll>’
typename factorization<Value / Divisor, Divisor + 1>::type>::type type;
^
prog.cpp:32:8: error: candidates are: struct factorization<Value, Divisor, Prime>
struct factorization<Value, Divisor, Prime>
^
prog.cpp:41:8: error: struct factorization<Value, Divisor, Prime, Primes ...>
struct factorization<Value, Divisor, Prime, Primes...>
^
prog.cpp:53:8: error: struct factorization<Value, Value, Primes ...>
struct factorization<Value, Value, Primes...>
^
prog.cpp:36:79: error: invalid use of incomplete type ‘struct factorization<2ll, 2ll, 2ll>’
typename factorization<Value / Divisor, Divisor + 1>::type>::type type;
^
prog.cpp:10:8: error: declaration of ‘struct factorization<2ll, 2ll, 2ll>’
struct factorization;
^
prog.cpp: In function ‘int main()’:
prog.cpp:67:30: error: invalid combination of multiple type-specifiers
typename factorization<18>::type x;
^
prog.cpp:67:36: error: invalid type in declaration before ‘;’ token
typename factorization<18>::type x;
^
prog.cpp:67:35: warning: unused variable ‘x’ [-Wunused-variable]
typename factorization<18>::type x;
^
Compilation error time: 0 memory: 0 signal:0
prog.cpp: In function ‘int main()’:
prog.cpp:67:30: error: ‘type’ in ‘struct factorization<18ll>’ does not name a type
typename factorization<18>::type x;
^
prog.cpp:67:36: error: invalid type in declaration before ‘;’ token
typename factorization<18>::type x;
^
prog.cpp:67:35: warning: unused variable ‘x’ [-Wunused-variable]
typename factorization<18>::type x;
^
如何解决这个问题?
这是一个工作版本。 请注意,使用 std::conditional
是一个坏主意,因为两个分支仍然需要扩展。 专业化效果要好得多。
// List of factors
template<std::intmax_t...>
struct factors { };
// Declaration
template<bool no_remainder, std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_remove_repeated;
template<bool no_remainder, std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_check;
// wraps the remainder check to reduce code duplication
template<template<bool, std::intmax_t ...> class T, std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ...Primes>
struct factorization_advance
{
typedef typename T<(Value % Divisor) == 0, Value, Divisor, Primes...>::type type;
};
// end case
template<template<bool, std::intmax_t ...> class T, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_advance<T, 1, Divisor, Primes...>
{
typedef factors<Primes...> type;
};
// No more repeats of Divisor, move to Divisor+1
template<std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_remove_repeated<false, Value, Divisor, Primes...>
{
typedef typename factorization_advance<factorization_check, Value, Divisor + 1, Primes...>::type type;
};
// removed a repeat of Divisor, continue doing so, without adding to primes list
template<std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_remove_repeated<true, Value, Divisor, Primes...>
{
typedef typename factorization_advance<::factorization_remove_repeated, Value / Divisor, Divisor, Primes...>::type type;
};
// found that Divisor isn't a factor, move to Divisor+1
template<std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_check<false, Value, Divisor, Primes...>
{
typedef typename factorization_advance<::factorization_check, Value, Divisor + 1, Primes...>::type type;
};
// Found first occurrence of a factor, add to primes list, remove repeats
template<std::intmax_t Value, std::intmax_t Divisor, std::intmax_t ... Primes>
struct factorization_check<true, Value, Divisor, Primes...>
{
typedef typename factorization_advance<factorization_remove_repeated, Value / Divisor, Divisor, Primes..., Divisor>::type type;
};
// Convenience wrapper
template<std::intmax_t Value>
struct factorization
{
typedef typename factorization_advance<factorization_check, Value, 2>::type type;
};
演示:http://rextester.com/NPGBU58803
早期版本也可以工作,但可维护性较差的IMO:http://ideone.com/Ia9hnd
没有与
factorization<18>
匹配的专业化(据我所知),除非您省略一些代码。你的每一个专业似乎都假设至少有两个参数被传递到因式分解中。
从您添加的评论来看,您似乎假设标记为"初始专业化"的专业化将捕获您只传入单个数字的情况。这不是真的。尝试运行factorization<18, 2>
以查看其实际效果。如果这确实是您想要的,那么要么省略您的专业化中的 2 并保持身体不变,要么添加一个最终专业化,该专业仅匹配单个数字并将 type
设置为 typename factorization<N, 2>::type
.
相关文章:
- C++类错误中的模板专用化
- 模板专用化会导致未定义的引用错误
- flat_hash_map.h:错误 C3203:"templated_iterator":非专用类模板
- C++ 将派生类的成员函数指针作为参数传递时选择了错误的模板专用化
- cpp 模板专用化,错误说参数 1 的类型为 T,这取决于参数 T
- 类模板部分专用化:编译器错误
- 为什么在源文件中专用模板不会导致错误?
- 函数模板(它是类模板的成员)的显式专用化会产生"partial specialization is not allowed"错误,为什么?
- C++模板 - 使用"std::is_same_v"而不是专用并避免编译错误?
- VS2017模板专用化错误无法从'Class *(__cdecl *)(Args...)'转换为'Class *(__cdecl *)(Args...)'
- 函数模板专用化生成链接错误
- 错误 C2908:显式专用化; 已被实例化
- 部分模板专用化错误
- 模板函数专用化的内部编译器错误
- 类模板方法的专用化,类型名称是类模板 - 错误:参数处的类型/值不匹配
- 错误 C2893:无法使用 CTPL 专用化函数模板
- gcc中变量模板的错误显式模板专用化
- Qt nmake:错误 C3203:"map":非专用类模板不能用作模板参数"base"的模板参数,预期为真实类型
- 声明无法解决"实例化后的显式专用化"错误
- 需要"override"案例时重叠模板部分专用化:如何避免错误?