enable_if检查迭代器的值类型是否为一对
enable_if to check if value type of iterator is a pair
我想为值类型为一对的迭代器编写一个专门的模板函数。我的期望是这应该匹配 std::map 的迭代器。
为了检测该对:
template <typename>
struct is_pair : std::false_type
{ };
template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type
{ };
// also tried this, but it didn't help
template <typename T, typename U>
struct is_pair<std::pair<const T, U>> : std::true_type
{ };
然后我在函数声明中使用enable_if:
template<class ITR>
decltype(auto) do_stuff(
std::enable_if<is_pair<typename ITR::value_type>::value, ITR> itr) {
//access of itr->second ok.
}
但是,当我将此函数与映射迭代器一起使用时,我从 clang (Xcode 8.3( 收到以下错误消息:
忽略候选模板:无法将"enable_if"与"__map_iterator"匹配
没有进一步的解释,如果不匹配,为什么要启用。
在检查__map_iterator类型时,看起来它应该与is_pair检查相匹配。
最好std::enable_if
移动到另一个默认模板参数,如下所示:
template<class ITR, typename = typename std::enable_if<is_pair<typename ITR::value_type>::value, ITR>::type>
decltype(auto) do_stuff(ITR && itr) {
//access of itr->second ok.
}
这不会阻止参数推导,因为ITR && itr
现在是一个通用参考。
完整示例:
#include <type_traits>
#include <utility>
#include <map>
template <typename>
struct is_pair : std::false_type
{ };
template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type
{ };
template<class ITR, typename = typename std::enable_if<is_pair<typename ITR::value_type>::value, ITR>::type>
decltype(auto) do_stuff(ITR && itr) {
//access of itr->second ok.
}
int main()
{
std::map<int, int> foo{
{ 1, 2 },
{ 3, 4 },
};
do_stuff(foo.begin());
return 0;
}
活在 gcc.godbolt.org
我想
通了,基本上是: SFINAE 在返回类型中工作,但不作为模板参数工作
所以最后我使用了这个签名:
template<class ITR>
typename std::enable_if_t<is_pair<typename ITR::value_type>::value, ITR>::value_type::second_type& get_value_from_iterator(ITR itr)
引用是必需的,因为我需要对映射内值的实际引用。
不需要检查的常量版本。
我使用了类似于GreenScape提出的代码,但我做了一个小的调整。
我变了
template<class ITR, typename = typename std::enable_if<is_pair<typename ITR::value_type>::value, ITR>::type>
到
template<class ITR, typename = typename std::enable_if<is_pair<typename std::iterator_traits<ITR>::value_type>::value, ITR>::type>
使用它,不仅 std::vector 有效,而且 std::array。
相关文章:
- 是否可以初始化不可复制类型的成员变量(或基类)
- 是否可以从int转换为enum类类型
- 检查 std::shared_ptr<> 的当前底层类型是否为 T
- 函数作为模板参数,是否对返回类型强制约束
- JS相等运算符(如===)是否可以使用embind类型
- visual是否可以在c++中创建一个接收无限数量相同类型(或至少相当数量)参数的函数
- 检查函数返回类型是否与STL容器类型值相同
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 检查某些类型是否是模板类 std::optional 的实例化
- 是否有内置方法可以强制转换为不同的基础类型,但保留常量限定符?
- C++类型特征,以查看是否可以<uint32_t>对类型"K"的任何变量调用"static_cast(k)"
- boost 是否有按特殊类型值编码状态"compact optional"?
- 初始值设定项列表是否只接受使用相同类型的值初始化变量?
- 是否有任何建议来统一函数类型限定符并简化可恶的函数类型?
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 检查一个类型是否直接派生自"enable if"上下文中的另一个类型(是其子类型)
- 在运行时检查继承是否只有一种类型和 void*
- 给定一个C++嵌套的私有结构类型,是否有从文件范围静态函数访问它的策略
- 将类型声明为类型模板参数的模板参数的一部分是否合法?
- 当返回类型声明为 ListNode 时,我们是否可以返回 false<T>*