Max ([info]upnudge) wrote,
@ 2009-05-27 19:19:00
Previous Entry  Add to memories!  Tell a Friend  Next Entry
:-(
Нашел баг в MS C++ linker. Ну да, я использую темплейты (не очень много), но это же не повод, вызывать совсем другой метод.
Ну да, я это обошел. Но веры ему нет. И нет чтобы internal compiler error, как обычно....



(5 comments) - (Post a new comment)


[info]sim__sim
2009-05-27 05:39 pm UTC (link)
А что за баг? Короткий пример есть?

(Reply to this) (Thread)


[info]upnudge
2009-05-28 09:12 am UTC (link)

//------------------------------------------------
//Classes.h
#include <vector>

using namespace std;

struct A
{
  A();
  int x;
};

class C
{
  public:
    C();
    void check() const;

  private:
    struct B
    {
      B();
      double x;
      double y;
    };

  private:
    vector<A> av;
    vector<B> bv;
};

//--------------------------------------------------
// classes.cpp
#include "Classes.h"
#include "Filler.h"
#include <assert.h>

A::A():
  x (5)
{
}


C::C()
{
  Filler::fill<vector<A>, A>(5, av);
  Filler::fill<vector<B>, B>(5, bv);
}


C::B::B():
  x(0),
  y(0)
{
}

void C::check() const
{
  assert(av[0].x == 5);
  assert(bv[0].x == 0);
}


//---------------------------------------------------
//Filler.h
#include <vector>

using namespace std;

struct Filler
{
  template <class T>
  struct ItemCreater
  {
    virtual T createItem() { return T(); }
  };

  template <class TSTLContainer, typename T>
  static void fill(int size, TSTLContainer & container, ItemCreater<T> & creater = ItemCreater<T>());
};

template <class TSTLContainer, typename T>
static void Filler::fill(int size, TSTLContainer & container, ItemCreater<T> & creater)
{
  for(int i = 0; i != size; ++i)
  {
    container.insert(container.end(), creater.createItem());
  }
}


//---------------------------------------
// main.cpp
#include "Filler.h"
#include "Classes.h"

void main()
{
  C c;
  c.check();
}
</code></pre>

(Reply to this) (Parent)


[info]upnudge
2009-05-28 09:17 am UTC (link)
Пример не очень короткий. Если запихать в один файл, то работает.
Баг в конструкторе С: во время вызова Filler::fill<vector<B>, B>(5, bv);
вызываектся ItemCreater<A> вместо ItemCreater<B>

(Reply to this) (Parent)


[info]sim__sim
2009-05-28 10:47 am UTC (link)

Если кратко — студия компилирует некорректный код, не выдавая при этом ошибок.

В примере, есть как минимум одна ошибка. При out-of-class определении шаблонной статической функции члене класса нельзя указывать static. В объявлении нужно, в определении нельзя.

Вторая погрешность не запрещена стандартом (на сколько я знаю), но потенциально может привести к неприятностям. Кстати, g++ считает ее ошибкой. Проблема в коде ItemCreater<T> & creater = ItemCreater<T>(). Неконстантная ссылка принимает временный объект. Нет нужды говорить об опасности такого подхода в общем случае.

Простейшая модификация кода, позволяющая корректно откомпилировать его студией — замена ItemCreater & creater = ItemCreater() на ItemCreater creater = ItemCreater().

Следующий вариант модификации:

struct Filler
{
    template <class TSTLContainer, typename T>
    static void fill(int size, TSTLContainer & container)
    {
        for (int i = 0; i != size; ++i)
        {
            container.insert(container.end(), T());
        }
    }

    template <class TSTLContainer, typename T, typename F>
    static void fill (int size, TSTLContainer & container, F creater)
    {
        for(int i = 0; i != size; ++i)
        {
            container.insert(container.end(), creater());
        }
    }
};
Это позволяет записывать инициализацию вот такими способами:
int foo()
{
    return 1;
}

struct bar
{
    double operator()()
    {
        return 1.0;
    }
};

void func()
{
    vector<char> av;
    Filler::fill<vector<char>, char>(5, av);

    vector<int> bv;
    Filler::fill<vector<int>, int>(5, bv, foo);

    vector<double> cv;
    Filler::fill<vector<double>, double>(5, cv, bar());
}

(Reply to this) (Thread)


[info]upnudge
2009-05-28 11:08 am UTC (link)
Спасибо, все замечания по делу. Невырожденный пример чуть сложнее, но то, что ты предложил, кажется там сработает.
Про неконстантную ссылку есть warning.

(Reply to this) (Parent)


(5 comments) - (Post a new comment)

Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…