我有一个函数模板来回应类中的内容,例如:
template<typename T>
void say(const std::vector<T>& ts)
{
for (const auto& t : ts) {
std::cout<<t.getDesc()<<std::endl;
}
}
class Base
{
public
Base();
const std::string& getDesc() const {
return m_desc;
}
protected:
std::string m_desc;
}
从Base
继承的所有对象都可以使用模板函数。
std::vector<Base> v;
Base a;
v.push_back(a)
但是当我转向std::reference_wrapper
时,功能模板不起作用。我应该写另一个模板来解决它。
template<typename T>
void say(const std::vector<std::reference_wrapper<T>>& ts)
{
for (const auto& t : ts) {
std::cout<<t.get().getDesc()<<std::endl;
}
}
它们之间的唯一区别是std::reference_wrapper::get()
。
那么还有其他方法可以避免这个恼人的代码吗?或者我应该为我使用的所有函数编写std :: reference_wrapper版本模板吗?
答案 0 :(得分:3)
你不需要重写整个事情。只需使用一个间接级别。
namespace detail {
template<typename T>
constexpr T& get(T &t) { return t; }
template<typename T>
constexpr T const& get(T const &t) { return t; }
template<typename T>
constexpr T& get(std::reference_wrapper<T> rt) { return rt; }
}
template<typename T>
void say(const std::vector<T>& ts)
{
for (const auto& t : ts) {
std::cout<< detail::get(t) <<std::endl;
}
}
detail
命名空间中的上述函数当然可以重用(虽然可以更好地命名),并且可以使所有模板与std::reference_wrapper
一起使用。
答案 1 :(得分:1)
您可以使用帮助Unwrap
模板,例如boost::unwrap_reference
。或编写自己的,复制此other answer:
template< typename T >
struct UnwrapReference;
template< typename T >
struct UnwrapReference { typedef T type; }
template< >
struct UnwrapReference< std::reference_wrapper< T > > { typedef T type; }
现在你可以编写一个版本的函数来绑定它们(未经测试):
template<typename T>
void say(const std::vector<T>& ts)
{
for (const UnwrapReference<T>::type &t : ts) {
std::cout<<t.getDesc()<<std::endl;
}
}