我想为值类型为一对的迭代器编写一个专门的模板函数。我的期望是这应该与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
{ };
Run Code Online (Sandbox Code Playgroud)
然后我在函数声明中使用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.
}
Run Code Online (Sandbox Code Playgroud)
但是,当我将此功能与地图迭代器一起使用时,我从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.
}
Run Code Online (Sandbox Code Playgroud)
因为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;
}
Run Code Online (Sandbox Code Playgroud)
我弄清楚了,本质上是: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)
Run Code Online (Sandbox Code Playgroud)
需要引用是因为我需要对地图内的值的实际引用。
检查的 const 版本是不必要的。
归档时间: |
|
查看次数: |
824 次 |
最近记录: |