【问题标题】:<functional> (nested bind) problems with MSVC 2010MSVC 2010 的 <功能>(嵌套绑定)问题
【发布时间】:2011-04-29 21:36:51
【问题描述】:

我有以下代码(抱歉冗长):

double primeValue( const func1D &func,
                   const double lowerBound, const double upperBound,
                   const double pole )
{
    // check bounds
    if( lowerBound >= upperBound )
        throw runtime_error( "lowerBound must be smaller than upperBound!" );

    // C++0x way of writing: fullFunc(x) = func(x)/(x-a)
    func1D fullFunc =
            bind( divides<double>(),              // division of
                  bind(func, _1),                 // f(x), with _1 = x
                  bind(minus<double>(), _1, pole) ); // by x-a, with _1 = x

    // pole not in domain
    if( pole<lowerBound || pole>upperBound)
    {
        cout << "Case 1" << endl;
        return integrateSimpson( fullFunc, 1000, lowerBound, upperBound );
    }
    // pole closer to upper bound
    else if( upperBound-pole < pole-lowerBound  )
    {
       cout << "Case 2" << endl;
       // C++0x way of writing g(x) := [f(x)-f(2a-x)]/(x-a)
       func1D specialFirstFunc =
                bind( std::divides<double>(),                               // division of
                      bind(minus<double>(),                                 // numerator:
                           bind(func, _1),                                  // f(x) minus
                           bind(func, bind(minus<double>(), 2.*pole, _1))), //f(2a-x)
                      bind(minus<double>(), _1, pole) );                    // denominator: x-a
        const double trickyPart = integrateSimpson( specialFirstFunc, 1000, pole+.000001, upperBound );

        const double normalPart = integrateSimpson( fullFunc, 1000, lowerBound, 2.*pole-upperBound );
        cout << "Tricky part: " << trickyPart << endl;
        cout << "Normal part: " << normalPart << endl;
        return trickyPart + normalPart;
    }
    else // pole closer to lower bound
    {
        cout << "Case 3" << endl;
        // C++0x way of writing g(x) := [f(x)-f(2a-x)]/(x-a)
        func1D specialFirstFunc =
                 bind( std::divides<double>(),                               // division of
                       bind(minus<double>(),                                 // numerator:
                            bind(func, _1),                                  // f(x) minus
                            bind(func, bind(minus<double>(), 2.*pole, _1))), //f(2a-x)
                       bind(minus<double>(), _1, pole) );                    // denominator: x-a
         const double trickyPart = integrateSimpson( specialFirstFunc, 1000, lowerBound, pole-.00001 );

         const double normalPart = integrateSimpson( fullFunc, 1000, 2.*pole-lowerBound, upperBound );
         cout << "Tricky part: " << trickyPart << endl;
         cout << "Normal part: " << normalPart << endl;
         return trickyPart + normalPart;
    }
}

它使用复杂分析数学域中的主值概念对包含奇点(极点)的实轴上的函数进行积分。 bindfunction 部分将原函数 f(x) 修改为

(f(x)-f(2*pole-x))/(x-a)

它甚至为我的简单测试用例功能提供了正确的结果。如果需要,我可以提供其他详细信息:

typedef std::function<double (double)> func1D;
double integrateSimpson( func1D, const size_t nSteps, const double lowerBound, const double upperBound);

后者使用简单的 Simpson 积分规则进行积分。可以提供代码,但与手头的问题不太相关。

这可以在 GCC 4.4+ 上正常编译(使用 4.4.5 和 4.5.2 预发行版进行测试,CFLAGS="-O2 -std=c++0x -pedantic -Wall -Wextra"),但会产生内部标头错误 (C2664 ) 在 MSVC 2010 上。(如果需要,我可以提供错误输出,我的代码完全没有引用(!))。

我在 MSVC 中发现错误了吗?

谢谢!

【问题讨论】:

  • "我在 MSVC 中发现错误了吗?" - 如果你这样做了,我不会感到惊讶。 :)
  • 这可能是相关的:stackoverflow.com/questions/2425277/… 但我不明白接受的答案建议做什么......

标签: c++ visual-studio-2010 gcc c++11 functional-programming


【解决方案1】:

为什么不直接使用 lambda?出于这种目的,所有绑定的东西都已被弃用。

double primeValue( const func1D &func,
                   const double lowerBound, const double upperBound,
                   const double pole )
{
    // check bounds
    if( lowerBound >= upperBound )
        throw runtime_error( "lowerBound must be smaller than upperBound!" );

    // C++0x way of writing: fullFunc(x) = func(x)/(x-a)
    auto fullFunc = [=](double d) {
        return func(d) / (d - pole);
    };

    // pole not in domain
    if( pole<lowerBound || pole>upperBound)
    {
        cout << "Case 1" << endl;
        return integrateSimpson( fullFunc, 1000, lowerBound, upperBound );
    }
    // pole closer to upper bound
    else if( upperBound-pole < pole-lowerBound  )
    {
       cout << "Case 2" << endl;
       // C++0x way of writing g(x) := [f(x)-f(2a-x)]/(x-a)
       auto specialFirstFunc = [=](double x) -> double {
           double numerator = func(x) - func(2*pole - x);
           return numerator / (x - pole);
       };
        const double trickyPart = integrateSimpson( specialFirstFunc, 1000, pole+.000001, upperBound );

        const double normalPart = integrateSimpson( fullFunc, 1000, lowerBound, 2.*pole-upperBound );
        cout << "Tricky part: " << trickyPart << endl;
        cout << "Normal part: " << normalPart << endl;
        return trickyPart + normalPart;
    }
    else // pole closer to lower bound
    {
        cout << "Case 3" << endl;
        // C++0x way of writing g(x) := [f(x)-f(2a-x)]/(x-a)
       auto specialFirstFunc = [=](double x) -> double {
           double numerator = func(x) - func(2*pole - x);
           return numerator / (x - pole);
       };
         const double trickyPart = integrateSimpson( specialFirstFunc, 1000, lowerBound, pole-.00001 );

         const double normalPart = integrateSimpson( fullFunc, 1000, 2.*pole-lowerBound, upperBound );
         cout << "Tricky part: " << trickyPart << endl;
         cout << "Normal part: " << normalPart << endl;
         return trickyPart + normalPart;
    }
}

至于你是否真的在 MSVC 中发现了一个错误,我不知道,但你的解决方案绝对是不必要的 - 这段代码更干净,更容易维护。

【讨论】:

  • 好吧,因为大多数 linux 发行版和我自己仍然使用 GCC 4.4,所以不能选择 lambda。我不认为 std::bind 已经被弃用了......但是 lambda 比以前向我展示的要短得多:stackoverflow.com/questions/4008369/…
  • @rubenvb:Lambda 被专门引入到语言中,因为绑定很糟糕,以及其他原因。只需在其上打一个#ifdef 即可。最有可能的是,MSVC 的库与 C++0x 现在作为标准的库有些过时了——例如,_1 被定义为 std::placeholders::_1 而不仅仅是 std::_1。我检查了该链接 - 他为他捕获的每个变量明确设置了引用或值,而我将我的设置为按值捕获所有变量。
  • @DeadMG:嗯,lambda 解决方法听起来不错,但我认为内部实现无论如何都使用std::bind(它给出了相同的错误:s)。我检查了使用的#ifdef 分支,它正在内部使用std::bind 编译lambda...
  • @ruben:我在 MSVC10 上进行了测试,可以向您保证上面发布的代码可以在 MSVC10 中编译。
  • 我有另一个嵌套的绑定函数代码位,我已将其替换为等效的 lambda,现在代码在 MSVC 10 下编译良好。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-04
  • 1970-01-01
  • 2011-07-26
  • 2018-12-05
  • 2011-09-03
  • 1970-01-01
相关资源
最近更新 更多