无法将枚举值传递给递归模板 (C++)
Can't Pass Enum Value to Recursive Template (C++)
假设我想编写一个递归模板函数,该函数将单个值与n维向量中的每个元素进行比较,如果至少有一个匹配项,则返回true,如果没有匹配项,则返回false。
我写了一些代码来做到这一点,尽管它可能远非最佳:
template <typename T, typename Checker>
void check_for_each(const T& v, const Checker condition)
{
condition(v);
}
template <typename T, typename Checker>
void check_for_each(const std::vector<T>& v, const Checker condition)
{
for(unsigned int i = 0; i < v.size(); i++)
{
check_for_each(v[i], condition);
}
}
template <typename T, typename U>
bool is_equal_any(const T& VALUE, const std::vector<typename U> VECTOR)
{
bool is_equal = false;
check_for_each(VECTOR, [&is_equal, &VALUE](const T& val)
{
if(!is_equal && VALUE == val)
{
is_equal = true;
}
});
return is_equal;
}
虽然这似乎有效,但我遇到了一个不寻常的问题,我不太理解它。 例如,以下代码有效:
enum PIECE_NAME {EMPTY, PAWN, ROOK, KNIGHT, BISHOP, QUEEN, KING};
std::vector<std::vector<int>> board {{ROOK, BISHOP}, {KNIGHT, QUEEN}};
std::cout << is_equal_any(2, board); // outputs 1 (there is a rook on the board)
然而,以下细微的变化并没有:
std::cout << is_equal_any(ROOK, board); // compile error C2664
显然我的函数无法弄清楚如何将枚举值转换为整数。 当然,我只能使用static_cast<int>(ROOK)
,代码按预期编译和运行,但这显然并不理想。 此外,我知道我可以将董事会的声明更改为std::vector<std::vector<PIECE_NAME>> board
,(它也按预期运行(,但我宁愿将其保留在int
.那么是否可以重写这些递归模板函数,以便is_equal_any
可以直接获取枚举值呢?我对C++仍然很陌生,所以我真的很感激你的回答中尽可能多的细节。 谢谢。
问题来自这里的类型T
:
check_for_each(VECTOR, [&is_equal, &VALUE](const T& val)
^
通过调用
is_equal_any(ROOK, board)
T
是一个PIECE_NAME
,但你最终作为参数传递给这个lambda的是你的向量的int
类型的元素。但是int
不能隐式转换为枚举。
您不能直接使用U
因为它可能是std::vector<int>
或std::vector< std::vector<int> >
,或者......
如果您使用的是 C++14,则可以使用带有auto
的通用 lambda
check_for_each(VECTOR, [&is_equal, &VALUE](const auto& val)
但是,当您将问题标记为C++11时,您可以使用一个特征:
template <typename T>
struct leaf_type {
using type = T;
};
template <typename T>
struct leaf_type<std::vector<T>> {
using type = typename leaf_type<T>::type;
};
template <typename T>
using leaf_type_t = typename leaf_type<T>::type;
用法:
check_for_each(VECTOR, [&is_equal, &VALUE](const leaf_type_t<U> & val)
演示
顺便说一句,您应该避免嵌套std::vector
s并将其线性化为单个,例如:
std::vector<int> board {ROOK, BISHOP, KNIGHT, QUEEN};
然后你可以很容易地使用std::find。
这是一个XY问题,因为有更好的方法:
- 使用作用域枚举
- 不要混合使用整数和枚举
- 将您的工作委托给
std::any_of
例如:
namespace multi_dim{
template< class InputIt, class UnaryPredicate >
bool any_of(InputIt first, InputIt last, UnaryPredicate p)
{
using std::any_of;
for(;first != last; ++first)
{
bool next = any_of(first->cbegin(), first->cend(), p);
if (next)
return true;
}
return false;
}
}
演示
测试:
std::vector<std::vector<PIECE>> board {{PIECE::ROOK, PIECE::BISHOP}, {PIECE::KNIGHT, PIECE::QUEEN}};
std::cout << std::boolalpha << multi_dim::any_of(board.cbegin(), board.cend(), [](PIECE p){return p == PIECE::ROOK;}) << std::endl;
std::cout << std::boolalpha << multi_dim::any_of(board.cbegin(), board.cend(), [](PIECE p){return p == PIECE::EMPTY;}) << std::endl;
输出:
真假
疯狂猜测:尝试为 VALUE 和 VECTOR 的元素类型使用差异模板参数。
我不使用 MSVC,所以我不确定您到底遇到了什么错误。
。不管怎样,我只需要重复我的评论:请不要写这种代码。
尽管使用std::any_of
的解决方案是最好的解决方案,但我给出的答案显示对原始代码的改进不那么剧烈。
template <typename T, typename Checker>
bool check_for_each(const T& v, const Checker condition)
{
return condition(v);
}
template <typename T, typename Checker>
bool check_for_each(const std::vector<T>& v, const Checker condition)
{
return std::find_if(begin(v), end(v), [condition](const T &t) { return check_for_each(t, condition); }) != v.end();
}
template <typename T, typename U>
bool is_equal_any(const T& value, const U &container)
{
return check_for_each(container, [&value](const T& val){ return value == val; });
}
enum class PIECE_NAME { EMPTY, PAWN, ROOK, KNIGHT, BISHOP, QUEEN, KING };
void test()
{
std::vector<std::vector<PIECE_NAME>> board
{
{ PIECE_NAME::ROOK, PIECE_NAME::BISHOP },
{ PIECE_NAME::KNIGHT, PIECE_NAME::QUEEN }
};
std::cout << is_equal_any(PIECE_NAME::ROOK, board);
}
此解决方案仍然是针对嵌套向量的硬编码,但代码已简化并进行了优化,因为一旦找到项目,它将停止搜索。
正如其他评论中已经建议的那样,您确实应该使用enum
(或者更好的是enum class
(。在向量中存储整数没有多大意义,因为您丢失了类型信息。
- 通过递归进行因子分解
- 递归函数计算序列中的平方和(并输出过程)
- 使用递归的数组的最小值.这是怎么回事
- 递归列出所有目录中的C++与Python与Ruby的性能
- 递归计数给定目录的文件和所有目录
- 如何在BST的这个简单递归实现中消除警告
- C++:正在检查LinkedList中的回文-递归方法-错误
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 递归无序映射
- TSP递归解的迭代形式
- 如何在Elixir中调用递归函数并行
- 返回递归调用和仅递归调用的区别
- 数组元素打印的递归方法
- 使用递归时获取变量的奇怪值
- 如何在C++中递归地按相反顺序打印集合
- 到连接组件算法的问题(递归)
- 如何使用递归打印修改后的星号三角形图案
- 使用递归模板动态分配的多维数组
- 递归函数有效,但无法记忆
- 包含模板文件的递归会导致编译失败