小编Mar*_*sen的帖子

C++ 11 std :: function比虚拟调用慢吗?

我正在创建一种机制,允许用户使用装饰器模式从基本构建块中形成任意复杂的函数.这可以很好地实现功能,但我不喜欢它涉及大量虚拟调用的事实,特别是当嵌套深度变大时.它让我担心,因为复杂的功能可能经常调用(> 100.000倍).

为了避免这个问题,我尝试将装饰器方案转换为std::function一次完成(to_function()在SSCCE中为cfr.).所有内部函数调用都是在构建期间连线的std::function.我认为这比原始装饰器方案评估更快,因为在std::function版本中不需要执行虚拟查找.

唉,基准测试证明我错了:装饰器方案实际上比std::function我建造的更快.所以现在我想知道为什么.也许我的测试设置有问题,因为我只使用两个简单的基本函数,这意味着可以缓存vtable查找?

我使用的代码包含在下面,不幸的是它很长.


SSCCE

// sscce.cpp
#include <iostream>
#include <vector>
#include <memory>
#include <functional>
#include <random>

/**
 * Base class for Pipeline scheme (implemented via decorators)
 */
class Pipeline {
protected:
    std::unique_ptr<Pipeline> wrappee;
    Pipeline(std::unique_ptr<Pipeline> wrap)
    :wrappee(std::move(wrap)){}
    Pipeline():wrappee(nullptr){}

public:
    typedef std::function<double(double)> FnSig;
    double operator()(double input) const{
        if(wrappee.get()) input=wrappee->operator()(input);
        return process(input);
    }

    virtual double process(double input) const=0;
    virtual ~Pipeline(){}

    // Returns a std::function which contains the entire Pipeline …
Run Code Online (Sandbox Code Playgroud)

c++ performance c++11

38
推荐指数
4
解决办法
8779
查看次数

返回值优化和副作用

返回值优化(RVO)是一种涉及复制省略的优化技术,它消除了在某些情况下为保存函数返回值而创建的临时对象.我一般都了解RVO的好处,但我有几个问题.

该标准在本工作草案的第12段第32段(强调我的)中说明了以下内容.

当满足某些条件时,允许实现省略类对象的复制/移动构造,即使该对象的复制/移动构造函数和/或析构函数具有副作用.在这种情况下,实现将省略的复制/移动操作的源和目标视为仅仅两种不同的引用同一对象的方式,并且该对象的销毁发生在两个对象的后期时间.没有优化就被破坏了.

然后,当实现可以执行此优化时,它会列出许多条件.


关于这种潜在的优化,我有几个问题:

  1. 我习惯于约束优化,以至于它们无法改变可观察的行为.此限制似乎不适用于RVO.我是否需要担心标准中提到的副作用?是否存在可能导致问题的角落案例?

  2. 作为程序员,我需要做什么(或不做)才能执行此优化?例如,以下是否禁止使用复制省略(由于move):

std::vector<double> foo(int bar){
    std::vector<double> quux(bar,0);
    return std::move(quux);
}
Run Code Online (Sandbox Code Playgroud)

编辑

我将此作为一个新问题发布,因为我提到的具体问题在其他相关问题中没有直接回答.

c++ compiler-optimization c++11

26
推荐指数
2
解决办法
1738
查看次数

在C++中实现可扩展工厂的优雅方式

我正在寻找一种直观和可扩展的方法来实现给定基类的子类的工厂.我想在库中提供这样的工厂函数.棘手的部分是我希望工厂也为用户定义的子类工作(例如,让库的工厂函数构建不同的子类,具体取决于链接到它的模块).目标是为下游开发人员使用工厂带来最小的负担/困惑.

我想要做的一个例子是:给定a std::istream,构造并返回与内容匹配的子类的对象,如果没有找到匹配则返回空指针.全球工厂的签名如下:

Base* Factory(std::istream &is){ ... };
Run Code Online (Sandbox Code Playgroud)

我熟悉原型工厂,但我更愿意避免制作/存储原型对象.这里发布了一个相关的问题::使用工厂允许最大的灵活性/可扩展性.

我目前不是在寻找特定的解决方案,但如果它们更优雅,我会很乐意了解这些.

我提出了一个工作解决方案,我相信它相当优雅,我将作为答案发布.我可以想象这个问题相当普遍,所以我想知道是否有人知道更好的方法.

编辑:似乎有些澄清是为了......

这个想法是让工厂构造派生类的对象,而不包含决定哪一个的逻辑.更糟糕的是,工厂方法最终将作为库的一部分,派生类可以在插件中定义.

派生类必须能够根据提供的输入(例如输入文件)自行决定它们是否适合构造.正如几个人所建议的那样,这个决定可以作为工厂可以使用的谓词来实现(顺便提一下,很好的建议!).

c++

24
推荐指数
2
解决办法
6309
查看次数

为什么在C++ 11中需要添加trailing-return-types?

我终于开始阅读,我不明白为什么需要trailing-return-types.

我遇到了以下示例,用于突出显示问题:

template<class Lhs, class Rhs>
  decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs) {return lhs + rhs;} 
Run Code Online (Sandbox Code Playgroud)

这个例子是非法的,因为decltype(lhs+rhs)没有工作,因为标识符lhsrhs仅解析阶段后有效.

我想我的问题是关于decltype类型解析的时间.如果我没有弄错,关键字decltype用于在编译时确定表达式的类型.

decltype在完成所有解析之后,我没有看到执行类型解析的缺点(这对于上面的示例可以正常工作).我相信这将是解决问题的一种更简单的方法......

相反,C++ 11标准提供了trailing-return-types:

template<class Lhs, class Rhs>
  auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;}
Run Code Online (Sandbox Code Playgroud)

我毫不怀疑我遗漏了一些东西,因为我没有看到其他使用trailing-return-types.我的推理中的缺陷在哪里?

trailing-return-types对我来说似乎是一个过于复杂的解决方案,因为decltype在解析完整的函数体之后具有类型解析也可以正常工作?

c++ compilation c++11 trailing-return-type

13
推荐指数
1
解决办法
635
查看次数

如何教Eclipse一些礼仪

我的Eclipse中的拼写检查器今天顽皮地建议亵渎(cfr.image).

在此输入图像描述

我该怎样才能防止它变得粗鲁?

c++ eclipse eclipse-cdt

11
推荐指数
1
解决办法
175
查看次数

习惯于条件列表理解的方法

我刚开始学习Haskell,我似乎找不到有条件地创建列表的好方法.

基本上,我想要的是列表理解与if/else但没有else部分.我确信这是可能的,我想我只是在google搜索任务中使用了错误的关键字.

Python中我想要Haskellize的一个非常愚蠢的例子:

[x for x in range(11) if x > 5]
Run Code Online (Sandbox Code Playgroud)

在Haskell中,据我所知,我们不能else像在Python示例中那样省略块.我该怎么做这样的事情?什么都不存在,我可以添加到else列表理解中的-block,如下所示:

[if x > 5 then x else Nothing | x <- [0..10]]
Run Code Online (Sandbox Code Playgroud)

我实际上在Haskell中遇到了Nothing,尽管我还没弄明白.它当然似乎没有做我希望的.基本上我不希望else我的列表理解,但如果它是一个必要的邪恶我想在else块中插入任何东西.

我可以想到一堆黑客可以非常低效地获得类似的功能:

  • filter 创建后的列表,例如 filter (>5) [0..10]
  • 使用列表推导创建列表列表,我可以在else块中创建一个空列表,然后是concat它们,例如concat [if x > 5 then [x] else [] | x <- [0..10]]

这些想法都显得实在难看,虽然.

在实践中,我不想创建具有这些微不足道条件的条件列表.

haskell list-comprehension

10
推荐指数
2
解决办法
8271
查看次数

工具链支持C++ 11标准

我目前正在将我对C++的知识更新为新标准.它让我觉得自己像个小孩子才能拥有最棒的玩具:我想一直玩它,但我不想因为它而失去我的朋友.

我参与了一些开源项目,其中一些新功能非常有用,所以我非常热衷于使用它们.我的问题是有多少用户可以编译C++ 11代码,例如,普通公众中C++ 11-complete编译器的采用率是多少?有没有人有相关信息?

我知道gcc 4.8.1clang 3.3是完整的C++ 11功能,但我不知道有多少人真正使用了最新的编译器.我知道大多数codemonkeys肯定会这样做,但是普通的开源用户呢?拍摄潜在用户并告诉他们更新他们的编译器并不是一个真正的选择.

我知道这个问题可能因为与这些问题相似而受到批评/关闭:

  1. 你今天如何使用C++ 11?
  2. 使用或不使用C++ 0x功能

我想指出现在情况有所不同,因为我们正在谈论一个实际批准的标准.我相信,在编程实践中,了解其采用率非常重要.

c++ c++11

7
推荐指数
1
解决办法
1288
查看次数

使用`std :: enable_if <std :: is_compound <double> :: value>的意外SFINAE行为

我有一个模板化的类,我想根据模板参数启用不同的构造函数.具体来说,我想std::is_compound用作标准.

SSCCE

// bla.cpp
#include <type_traits>
#include <vector>

template <typename T>
class Foo{
    double bar;
public:
    template<typename U=T, 
        class = typename std::enable_if<std::is_compound<U>::value>::type
        >
    Foo(typename T::value_type& b):bar(b){}

    template<typename U=T, 
        class = typename std::enable_if<!std::is_compound<U>::value>::type
        >
    Foo(T b):bar(b){}   
};

int main(){
    double d=1.0;
    Foo<std::vector<double>> f2(d); // works
    Foo<double> f1(d);          // compiler error
}
Run Code Online (Sandbox Code Playgroud)

我收到以下编译错误:

g ++ -std = gnu ++ 11 bla.cpp

bla.cpp: In instantiation of ‘class
Foo<double>’: bla.cpp:22:18:   required from here bla.cpp:11:2: error:
‘double’ is not a class, struct, or …
Run Code Online (Sandbox Code Playgroud)

c++ c++11

2
推荐指数
1
解决办法
168
查看次数

在gcc 4.7中使用std :: bind编译错误

std::bind在代码的各个地方使用时遇到了很多麻烦.有时候它会起作用,有时却不起作用,所以我认为我做的事情根本就是错误的.

据我了解,以下基本用法std::bind应该可以正常工作:

#include <functional>

int foo(int a, int b){ return a+b; }

int main(){

    using namespace std::placeholders;

    // works
    auto bar_auto=std::bind(foo,1,_2);

    // compile error
    std::function<int(int)> bar_fun=std::bind(foo,1,_2);

    int quux=1;
    // compile error
    std::function<int(int)> bar_fun_lvalue=std::bind(foo,quux,_2);

}
Run Code Online (Sandbox Code Playgroud)

毫无疑问的类型bar_autostd::function<int(int)>(类型foo1个int参数绑定),所以为什么bar_fun编译失败?我包括bar_fun_lvalue因为一些谷歌搜索向我显示rvalues曾经是有问题的.但这并没有解决任何问题.

它类似于这个bug,但是它太旧了我不认为它是相关的.

gcc的输出不是特别有启发性:

在bindnew.cpp中包含的文件中:1:0:/usr/include/c++/4.7/functional:在'static _Res std :: _ Function_handler <_Res(_ArgTypes ...),_Functor> :: _ M_invoke(const std)的实例化中:: _ Any_data&,_ ArgTypes ...)[with _Res = int; _Functor = std :: …

c++11

1
推荐指数
1
解决办法
1467
查看次数