MSVC 2013 错误?从映射容器中检索最后一个元素
MSVC 2013 Bug? Retrieving last element from mapped container
说我有一个 std::map<std::string, std::vector<T>
并且我想写一些代码
这将 return 映射向量后面的元素,给定一些键。
所以我首先编写一些代码,将 return 集合末尾的元素(在本例中为向量):
// get element at back of given collection
template<typename Collection>
auto ReturnLastObject(const Collection& collection) -> decltype(collection.back())&
{
return collection.back();
}
到目前为止一切顺利。
接下来,我意识到我的函数实际执行逻辑将需要 return 与 ReturnLastObject
相同的类型,所以我编写了一些辅助结构,允许我使用类型特征拉出 return 类型的函数指针(预计函数指针将指向 ReturnLastObject<U>
):
template<typename T>
struct GetReturnType;
template<typename Ret, typename... Args>
struct GetReturnType<Ret(*)(Args...)>
{
using type = Ret;
};
还不错:
最后,我将主函数写到 return 最后一个元素,或者抛出异常:
template<typename MapType>
auto GetLastAddedObject(const typename MapType::key_type& key, const MapType& mapCollection)
-> typename GetReturnType<decltype(&ReturnLastObject<typename MapType::mapped_type>)>::type&
{
auto& objects = mapCollection.at(key);
if (!objects.empty())
{
return ReturnLastObject(objects);
}
else
{
throw std::runtime_error("Could not retrieve last added item.");
}
}
中都能正常工作
但是,当我尝试使用 MSVC 2013(更新 3)进行编译时,
我收到以下编译器错误:
error C2893: Failed to specialize function template GetReturnType<unknown-type>::type &detail::GetLastAddedObject(const MapType::key_type &,const MapType &)
With the following template arguments:
MapType=std::map<std::string,std::vector<int,std::allocator<_Ty>>,std::less<_Kty>,std::allocator<std::pair<const _Kty,std::vector<_Ty,std::allocator<_Ty>>>>>
问题
我想问的是 MSVC 2013 中是否有解决方法可以完成同样的事情,或者我只是做错了什么?
编辑:MCVE
(也可以通过 GCC 和 Clang 链接找到)
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <type_traits>
#include <utility>
namespace detail{
// helper struct for peeling off return type of function pointer
template<typename T>
struct GetReturnType;
template<typename Ret, typename... Args>
struct GetReturnType<Ret(*)(Args...)>
{
using type = Ret;
};
// get element at back of given collection
template<typename Collection>
auto ReturnLastObject(const Collection& collection) -> decltype(collection.back())&
{
return collection.back();
}
// GetLastAddedObject assumes that MapType is essentially a key mapped to a collection
// and we want to access the collection specified by the key, and return the element at the back of it
template<typename MapType>
auto GetLastAddedObject(const typename MapType::key_type& key, const MapType& mapCollection)
-> typename GetReturnType<decltype(&ReturnLastObject<typename MapType::mapped_type>)>::type&
{
auto& objects = mapCollection.at(key);
if (!objects.empty())
{
return ReturnLastObject(objects);
}
else
{
throw std::runtime_error("Could not retrieve last added item.");
}
}
} //end namespace detail
int main()
{
std::map<std::string, std::vector<int>> myMap;
myMap["Whosebug"] = {42};
//...
std::string key = "Whosebug";
auto&& lastAddedObject = detail::GetLastAddedObject(key, myMap);
std::cout << std::forward<decltype(lastAddedObject)>(lastAddedObject) << std::endl; // should print "42
}
您可以简化您的 return 类型:
template<typename MapType>
auto GetLastAddedObject(const typename MapType::key_type& key,
const MapType& mapCollection)
-> decltype(ReturnLastObject(mapCollection.at(key)))
这对你有用吗?
我没有 VS2013 来测试它。
namespace detail {
template<typename MapType>
typename MapType::mapped_type::value_type GetLastAddedObject(const typename MapType::key_type key, const MapType& mapCollection)
{
auto& objects = mapCollection.at(key);
if (!objects.empty())
{
return objects.back();
}
else
{
throw std::runtime_error("Could not retrieve last added item.");
}
}
} //end namespace detail
说我有一个 std::map<std::string, std::vector<T>
并且我想写一些代码
这将 return 映射向量后面的元素,给定一些键。
所以我首先编写一些代码,将 return 集合末尾的元素(在本例中为向量):
// get element at back of given collection
template<typename Collection>
auto ReturnLastObject(const Collection& collection) -> decltype(collection.back())&
{
return collection.back();
}
到目前为止一切顺利。
接下来,我意识到我的函数实际执行逻辑将需要 return 与 ReturnLastObject
相同的类型,所以我编写了一些辅助结构,允许我使用类型特征拉出 return 类型的函数指针(预计函数指针将指向 ReturnLastObject<U>
):
template<typename T>
struct GetReturnType;
template<typename Ret, typename... Args>
struct GetReturnType<Ret(*)(Args...)>
{
using type = Ret;
};
还不错:
最后,我将主函数写到 return 最后一个元素,或者抛出异常:
template<typename MapType>
auto GetLastAddedObject(const typename MapType::key_type& key, const MapType& mapCollection)
-> typename GetReturnType<decltype(&ReturnLastObject<typename MapType::mapped_type>)>::type&
{
auto& objects = mapCollection.at(key);
if (!objects.empty())
{
return ReturnLastObject(objects);
}
else
{
throw std::runtime_error("Could not retrieve last added item.");
}
}
中都能正常工作
但是,当我尝试使用 MSVC 2013(更新 3)进行编译时, 我收到以下编译器错误:
error C2893: Failed to specialize function template
GetReturnType<unknown-type>::type &detail::GetLastAddedObject(const MapType::key_type &,const MapType &)
With the following template arguments:
MapType=std::map<std::string,std::vector<int,std::allocator<_Ty>>,std::less<_Kty>,std::allocator<std::pair<const _Kty,std::vector<_Ty,std::allocator<_Ty>>>>>
问题
我想问的是 MSVC 2013 中是否有解决方法可以完成同样的事情,或者我只是做错了什么?
编辑:MCVE
(也可以通过 GCC 和 Clang 链接找到)
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <type_traits>
#include <utility>
namespace detail{
// helper struct for peeling off return type of function pointer
template<typename T>
struct GetReturnType;
template<typename Ret, typename... Args>
struct GetReturnType<Ret(*)(Args...)>
{
using type = Ret;
};
// get element at back of given collection
template<typename Collection>
auto ReturnLastObject(const Collection& collection) -> decltype(collection.back())&
{
return collection.back();
}
// GetLastAddedObject assumes that MapType is essentially a key mapped to a collection
// and we want to access the collection specified by the key, and return the element at the back of it
template<typename MapType>
auto GetLastAddedObject(const typename MapType::key_type& key, const MapType& mapCollection)
-> typename GetReturnType<decltype(&ReturnLastObject<typename MapType::mapped_type>)>::type&
{
auto& objects = mapCollection.at(key);
if (!objects.empty())
{
return ReturnLastObject(objects);
}
else
{
throw std::runtime_error("Could not retrieve last added item.");
}
}
} //end namespace detail
int main()
{
std::map<std::string, std::vector<int>> myMap;
myMap["Whosebug"] = {42};
//...
std::string key = "Whosebug";
auto&& lastAddedObject = detail::GetLastAddedObject(key, myMap);
std::cout << std::forward<decltype(lastAddedObject)>(lastAddedObject) << std::endl; // should print "42
}
您可以简化您的 return 类型:
template<typename MapType>
auto GetLastAddedObject(const typename MapType::key_type& key,
const MapType& mapCollection)
-> decltype(ReturnLastObject(mapCollection.at(key)))
这对你有用吗?
我没有 VS2013 来测试它。
namespace detail {
template<typename MapType>
typename MapType::mapped_type::value_type GetLastAddedObject(const typename MapType::key_type key, const MapType& mapCollection)
{
auto& objects = mapCollection.at(key);
if (!objects.empty())
{
return objects.back();
}
else
{
throw std::runtime_error("Could not retrieve last added item.");
}
}
} //end namespace detail