首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在C++11中使用auto和decltype

在C++11中使用auto和decltype
EN

Stack Overflow用户
提问于 2009-07-07 18:39:03
回答 3查看 6.7K关注 0票数 8

我正在尝试学习目前被接受的c++11功能,但我在自动和解密方面遇到了麻烦。作为学习练习,我用一些泛型函数扩展了std类列表。

代码语言:javascript
复制
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; });

对于成员映射,我希望返回类型是泛型的,这取决于传递的函数返回的内容。所以对于返回类型,我可以这样做。

代码语言:javascript
复制
auto map(const function<float (_Ty)>& f) -> FList<decltype(f(_Ty))>*

这还需要删除函数模板中的float类型。

代码语言:javascript
复制
auto map(const function<auto (_Ty)>& f) -> FList<decltype(f(_Ty))>*

我可以使用模板类,但这会使实例的使用更加繁琐,因为我必须指定返回类型。

代码语言:javascript
复制
template<class T> FList<T>* map(const function<T (_Ty)>& f)

总结我的问题,我试图弄清楚如何在不使用模板类的情况下定义map,并且仍然在它返回的类型中保持它的泛型。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-07-07 18:45:40

不鼓励从std::list或其他std::容器派生。

将您的操作编写为自由函数,以便它们可以通过迭代器在任何标准容器上工作。

你的意思是“不使用模板函数来定义map”吗?

您应该能够使用std::functionresult_type成员类型来获取它返回的类型。

此外,您也没有必要指定该函数作为std::function传递。您可以将其作为任何类型保持开放,并让编译器将所有内容连接起来。您只需要将std::function用于运行时多态性。

使用new创建原始堆分配对象并通过指针返回它们是SOOOO1992!:)

你的iter函数本质上和range-based for loop是一样的。

但抛开这一切...你是说像这样的东西吗?

代码语言:javascript
复制
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;
}

这将匹配任何可调用的内容,并通过使用decltype确定函数的返回类型。

请注意,它要求_Ty是默认可构造的。你可以通过制造一个实例来解决这个问题:

代码语言:javascript
复制
template <class T>
T make_instance();

不需要实现,因为没有生成调用它的代码,所以链接器没有什么可抱怨的(感谢dribeas指出了这一点!)

所以代码现在变成了:

代码语言:javascript
复制
FList<decltype(f(make_instance<_Ty>()))>*

或者,从字面上来说,是一个列表,其中包含您通过引用_Ty实例调用函数f所得到的任何类型。

作为接受的免费奖励,查找rvalue引用-这些将意味着你可以写:

代码语言:javascript
复制
std::list<C> make_list_somehow()
{
    std::list<C> result;
    // blah...
    return result;
}

然后这样叫它:

代码语言:javascript
复制
std::list<C> l(make_list_somehow());

因为std::list将有一个“移动构造函数”(类似于复制构造函数,但在参数是临时参数时选择,就像这里),所以它可以窃取返回值的内容,即执行与优化swap相同的操作。所以不会复制整个列表。(这就是为什么C++0x会让天真编写的现有代码运行得更快--许多流行但丑陋的性能技巧将会过时)。

通过使用unique_ptr,您可以为您自己的任何现有类免费获得相同类型的东西,而无需编写正确的移动构造函数。

代码语言:javascript
复制
std::unique_ptr<MyThing> myThing(make_my_thing_somehow());
票数 18
EN

Stack Overflow用户

发布于 2011-10-27 04:46:55

你不能在你想要推断参数类型的函数参数中使用auto。为此,您可以使用模板。看看:http://thenewcpp.wordpress.com/2011/10/18/the-keyword-auto/http://thenewcpp.wordpress.com/2011/10/25/decltype-and-declval/。他们都解释了如何使用auto和decltype。他们应该给你足够的关于如何使用它们的信息。特别是,关于make_instance的另一个答案可以用declval做得更好。

票数 0
EN

Stack Overflow用户

发布于 2011-10-27 11:06:50

我认为贾拉在他的回答中提出的观点是,这些观点确实解释了如何使用这些东西。无论如何,我都会指出细节:

你不能这样做,有两件事是错的:

代码语言:javascript
复制
auto map(const function<auto (_Ty)>& f) -> FList<decltype(f(_Ty))>*

auto不能用于函数参数。如果你想要推导出函数的类型,那么你应该使用模板。第二个是decltype接受一个表达式,而_Ty是一个类型。下面是如何解决这个问题:

代码语言:javascript
复制
template <typename Ret>
auto
map(const function<Ret (_Ty)>& f)
  -> FList<decltype(f(declval<_Ty>()))>
{}

这样就不会有创建类型实例的魔力了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1094046

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档