gra*_*bot 8 c++ templates decltype auto c++11
我正在尝试学习当前接受的c ++ 11功能,而我遇到了auto和decltype的问题.作为一个学习练习,我正在使用一些通用函数扩展std类列表.
template<class _Ty, class _Ax = allocator<_Ty>>
class FList : public std::list<_Ty, _Ax>
{
public:
void iter(const function<void (_Ty)>& f)
{
for_each(begin(), end(), f);
}
auto map(const function<float (_Ty)>& f) -> FList<float>*
{
auto temp = new FList<float>();
for (auto i = begin(); i != end(); i++)
temp->push_back(f(*i));
return temp;
}
};
auto *ints = new FList<int>();
ints->push_back(2);
ints->iter([](int i) { cout << i; });
auto *floats = ints->map([](int i) { return (float)i; });
floats->iter([](float i) { cout << i; });
Run Code Online (Sandbox Code Playgroud)
对于成员映射,我希望返回类型是通用的,具体取决于传递的函数返回的内容.所以对于返回类型我可以做这样的事情.
auto map(const function<float (_Ty)>& f) -> FList<decltype(f(_Ty))>*
Run Code Online (Sandbox Code Playgroud)
这还需要删除函数模板中的float类型.
auto map(const function<auto (_Ty)>& f) -> FList<decltype(f(_Ty))>*
Run Code Online (Sandbox Code Playgroud)
我可以使用模板类,但这使得实例的使用更加冗长,因为我必须指定返回类型.
template<class T> FList<T>* map(const function<T (_Ty)>& f)
Run Code Online (Sandbox Code Playgroud)
总结我的问题,我试图弄清楚如何在不使用模板类的情况下定义地图,并且仍然在它返回的类型中使用它.
Dan*_*ker 18
不鼓励从std::list
其他std::
容器中获取.
将您的操作编写为自由函数,以便它们可以通过迭代器在任何标准容器上工作.
你的意思是"不使用模板功能定义地图"?
您应该能够使用result_type
成员类型std::function
来获取它返回的类型.
此外,您无需指定函数作为a传递std::function
.您可以将其保持为任何类型,并让编译器加入所有类型.您只需要std::function
运行时多态性.
使用new创建原始堆分配对象并通过指针返回它们是soooo 1992!:)
你的iter函数与基于范围的for循环基本相同.
但除此之外......你的意思是这样吗?
template <class TFunc>
auto map(const TFunc &f) -> FList<decltype(f(_Ty()))>*
{
auto temp = new FList<decltype(f(_Ty()))>();
for (auto i = begin(); i != end(); i++)
temp->push_back(f(*i));
return temp;
}
Run Code Online (Sandbox Code Playgroud)
这将匹配任何可调用的东西,并将使用decltype找出函数的返回类型.
请注意,它要求_Ty是默认构造的.您可以通过制造实例来解决这个问题:
template <class T>
T make_instance();
Run Code Online (Sandbox Code Playgroud)
不需要实现,因为没有生成调用它的代码,因此链接器没有什么可抱怨的(感谢dribeas指出这个!)
所以代码现在变成:
FList<decltype(f(make_instance<_Ty>()))>*
Run Code Online (Sandbox Code Playgroud)
或者,字面上,您可以通过引用_Ty实例调用函数f获得的类型列表.
并且作为接受的免费奖励,查找右值引用 - 这意味着您可以写:
std::list<C> make_list_somehow()
{
std::list<C> result;
// blah...
return result;
}
Run Code Online (Sandbox Code Playgroud)
然后像这样调用它:
std::list<C> l(make_list_somehow());
Run Code Online (Sandbox Code Playgroud)
因为std :: list将有一个"移动构造函数"(就像复制构造函数,但是当参数是临时的时候选择,就像这里一样),它可以窃取返回值的内容,即做同样的最佳值swap
.所以没有复制整个列表.(这就是为什么C++ 0x会使天真编写的现有代码运行得更快 - 许多流行但丑陋的性能技巧将变得过时).
而且你可以免费为自己的任何现有类获得相同类型的东西,而无需使用编写正确的移动构造函数unique_ptr
.
std::unique_ptr<MyThing> myThing(make_my_thing_somehow());
Run Code Online (Sandbox Code Playgroud)