Забавная ошибка
От: Tilir Россия http://tilir.livejournal.com
Дата: 23.07.08 09:53
Оценка:
Минимальный код воспроизведения на MSVC 2005 вот такой:

struct tagData{
  int somemember;
};

volatile struct tagData dataArray[10];

int funnyError(volatile struct tagData data){  
  return data.somemember;
}

int main(int /* argc */, char** /* argv */){
  dataArray[0].somemember = 1;
  int x = funnyError(dataArray[0]);
  return 0;
}


Получается классное сообщение об ошибке компиляции:

1>d:\programming\vcpp\research\funnyerr\funnyerr.cpp(13) : error C2664: 'funnyError' : cannot convert parameter 1 from 'volatile tagData' to 'volatile tagData'
1> Cannot copy construct struct 'tagData' due to ambiguous copy constructors or no available copy constructor


Вопрос к сообществу: что бы вы сделали, чтобы заставить это работать?

Моё решение -- передавать по указателю. То есть вот так:
struct tagData{
  int somemember;
};

volatile struct tagData dataArray[10];

int funnyError(volatile struct tagData* data){  
  return data->somemember;
}

int main(int /* argc */, char** /* argv */){
  dataArray[0].somemember = 1;
  int x = funnyError(dataArray);
  return 0;
}


Всё компилится и работает. Но мб есть иные методы?
Re: Забавная ошибка
От: Bell Россия  
Дата: 23.07.08 10:03
Оценка: 8 (3) +1
Здравствуйте, Tilir, Вы писали:

T>Всё компилится и работает. Но мб есть иные методы?


Ну можно добавить нехватающие конструкторы в tagData:

struct tagData{
  int somemember;
   tagData() : somemember(0) {}
   tagData(const volatile tagData& data) : somemember(data.somemember) {}
};
Любите книгу — источник знаний (с) М.Горький
Re: Забавная ошибка
От: remark Россия http://www.1024cores.net/
Дата: 23.07.08 10:38
Оценка: 68 (10)
Здравствуйте, Tilir, Вы писали:

T>Минимальный код воспроизведения на MSVC 2005 вот такой:


T>Получается классное сообщение об ошибке компиляции:


T>

1>>d:\programming\vcpp\research\funnyerr\funnyerr.cpp(13) : error C2664: 'funnyError' : cannot convert parameter 1 from 'volatile tagData' to 'volatile tagData'
1>> Cannot copy construct struct 'tagData' due to ambiguous copy constructors or no available copy constructor


T>Вопрос к сообществу: что бы вы сделали, чтобы заставить это работать?



Конструктор копирования, который генерируется по-умолчанию, имеет сигнатуру:
tagData& tagData::tagData(tagData const&);


Соотв. он не может принимать volatile объекты.
Тебе надо определить свой:
tagData& tagData::tagData(tagData const volatile&);


Но на этом сюрпризы не закончатся. operator = тоже не будет работать. При этом он не только не умеет принимать volatile объекты, но и не может вызываться для volatile объекта. Т.е. тебе надо будет определить свой:
tagData volatile& operator = (tagData const volatile&) volatile;


Вообще я лично пришёл к выводу, что объявление объектов типа класс с квалификатором volatile, ни к чему хорошему не приводит, и лучше так вообще не делать — больше проблем. volatile лучше объявлять только объекты примитивных типов, для них всё работает интуитивно по-умолчанию. Т.е. в твоём случае вот так:
struct tagData{
  int volatile somemember;
};




1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Забавная ошибка
От: gear nuke  
Дата: 23.07.08 12:30
Оценка: :)
Здравствуйте, Tilir, Вы писали:

T>что бы вы сделали, чтобы заставить это работать?


//namespase std {
template <bool, class IfTrueType, class IfFalseType> struct conditional;
template <class T, class F> struct conditional<true, T, F>  { typedef T type; }; 
template <class T, class F> struct conditional<false, T, F> { typedef F type; }; 
//}


template<bool IsVolatile = false>
struct tagData
{
  typedef typename conditional<IsVolatile, volatile int, int>::type somemember_type;
  somemember_type somemember;
};

tagData<true> dataArray[10];

tagData<true>::somemember_type funnyError(tagData<true> data)
{  
  return data.somemember;
}
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[2]: Забавная ошибка
От: gear nuke  
Дата: 24.07.08 06:50
Оценка:
Вообще, конечно, забавно, что играться с CV квалификаторами мемберов и явных параметров функций можно, на как быть с this
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[3]: Забавная ошибка
От: remark Россия http://www.1024cores.net/
Дата: 24.07.08 18:05
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Вообще, конечно, забавно, что играться с CV квалификаторами мемберов и явных параметров функций можно, на как быть с this



Точно так же:

#include <iostream>

struct X
{
    void f()
    {
        std::cout << typeid(this).name() << std::endl;
    }
    void f() const
    {
        std::cout << typeid(this).name() << std::endl;
    }
    void f() volatile
    {
        std::cout << typeid(this).name() << std::endl;
    }
    void f() const volatile
    {
        std::cout << typeid(this).name() << std::endl;
    }
};

int main()
{
    X().f();
    static_cast<X const&>(X()).f();
    static_cast<X volatile&>(X()).f();
    static_cast<X const volatile&>(X()).f();
}


Вывод:

struct X *
struct X const *
struct X volatile *
struct X const volatile *




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Забавная ошибка
От: gear nuke  
Дата: 25.07.08 00:14
Оценка:
Здравствуйте, remark, Вы писали:

R>Точно так же:


Дык у меня как раз без копипаста порождалось семейство...

Тогда что-то вроде, но не так ужасно в использовании:
struct X
{
  template<typename T> // упрощенно, на самом деле будет conditional<>::type, например
  static // ыыыыы :`(
  void f(T * This)
  {
    std::cout << typeid(This).name() << std::endl;
  }
};

int main()
{
  X x;
  X::f(&x);
  X::f(static_cast<X const*>(&x));
  X::f(static_cast<X volatile*>(&x));
  X::f(static_cast<X const volatile*>(&x));
}


Хотя интерес больше академический, скорее лучше имена разные давать:
// volatile инстанс по адресу 0x7ffe0014 даёт аналог NtQuerySystemTime без перехода в ядро
struct system_time
{
    typedef int64_t type;
  
    __forceinline type get() volatile const
    {
      uint32_t l; int32_t h;
      if ( sizeof(std::uintptr_t) > sizeof(int32_t) )// don't like #ifdef _M_X64
        return *reinterpret_cast<int64_t volatile const*>(this);
      do { cpu::pause(); l = low; h = high; }
      while ( h != high2 );
      return (type)h << 32 | l;
    }

    __forceinline operator type() const
    {
      return (type)high << 32 | low;
    }

    uint32_t  low;
    int32_t   high, high2;
};
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.