Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Поддержка частичной специализации шаблонов, отсутствует? 
:(
    Опции темы
vaddsm
  Дата 26.5.2009, 02:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Подскажите, пожалуйста есть ли возможность сделать на BCB 6.0 подобный код компилируемым:

Код


template <typename R> class callback_cast
{

};

template <class R, class T0 , class T1 , class T2 , class T3>
class callback_cast<R (__stdcall *)( T0 , T1 , T2 , T3)>
{

};



Или данный компилятор не поддерживает стандарт языка в полной мере?
PM MAIL   Вверх
Lazin
Дата 26.5.2009, 08:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 18
Всего: 154



частичная специализация шаблонов применяется в STL, следовательно BCB6 это умеет
PM MAIL Skype GTalk   Вверх
vaddsm
Дата 26.5.2009, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Спасибо, что присоединился к данному треду, думал тебя  выуживать из общего раздела по c++ .) Касательно проблемы. Совершенно очевидно что -- нет. Предположительно она должна поддерживаться, но видимо не в полной мере. Компилятор не верно парсирует функциональные типы. Приведенный мною код валиден в VC9.0 , Comeau и Mingw но не в Borland (.
PM MAIL   Вверх
Lazin
Дата 26.5.2009, 09:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 18
Всего: 154



ну, то что bcb6 не поддерживает стандарт в полной мере - известный факт
какой workaround здесь поможет я не знаю
PM MAIL Skype GTalk   Вверх
vaddsm
Дата 26.5.2009, 09:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Еще хочу дополнить пример вот таким фейлом: 

Код

 template <class C, class R, class T0 , class T1 , class T2 , class T3, 
 R (__stdcall C::*M)( T0 , T1 , T2 , T3)>
 class some
 {


 };


+ VC9.0
+ Comeau
- Mingw 
- Borland

Добавлено через 7 минут и 21 секунду
Прошу, взглянуть опытным взглядом и поставить вердикт относительно валидности приведенного кода. Буду очень рад совместимым с другими компиляторами предложениям по изменению кода. 
PM MAIL   Вверх
mrbrooks
Дата 26.5.2009, 09:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 167
Всего: 306



 smile 
меня всегда умилял тот факт, что сравнивают CB6 и VC9.
PM MAIL   Вверх
vaddsm
Дата 26.5.2009, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



))) Никто ничего не сравнивает, мне нужно добиться совместимости кода и только. Прошу не разжигать расовой ненависти в этом топике.
PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



vaddsm

С точки зрения С++ - нормальный код, с моей точки зрения - выглядет хреново, но это не мешает ему быть правильным.


Цитата(vaddsm @  26.5.2009,  09:01 Найти цитируемый пост)

+ VC9.0
+ Comeau
- Mingw 
- Borland

MinGW это откомпилирует по самые помидоры, наверное он на __stdcall ругается.
насчет борланда - не знаю, а в чем конкретно проблема и где выдается ошибка?

Добавлено через 3 минуты и 18 секунд
Код

 template <class C, class R, class T0 , class T1 , class T2 , class T3, 
 R (__stdcall C::*M)( T0 , T1 , T2 , T3)>
 class some
 {
 };

речь конкретно об этом куске кода

Добавлено через 7 минут и 7 секунд
Проверьте этот код.
Код

class C
{
public:
    void foo(T1 p1, T2 p2)
    {
        std::cout << "template " << p1 << " " << p2 << std::endl;
    }
};

template <class T1>
class C<T1, int>
{
public:
    void foo(T1 p1, int p2)
    {
        std::cout << "template specialization " << p1 << " " << p2 << std::endl;
    }
};

int main()
{
    C<int, std::string> t1;
    t1.foo(1, "hello");
    C<std::string, int> t2;
    t2.foo("hello", 1);
}


Это сообщение отредактировал(а) azesmcar - 26.5.2009, 09:51
PM   Вверх
vaddsm
Дата 26.5.2009, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



2 azesmcar. 

Ваш пример с небольшой коррекцией 

Код

[U]template<class T1, class T2>[/U]
class C
{
public:
    void foo(T1 p1, T2 p2)
    {
        std::cout << "template " << p1 << " " << p2 << std::endl;
    }
};


Естественно компилируется всюду. 

Однако, весьма странно, мой шаблон класса some действительно не компилировался в MinGW по причине указания в шаблоне соглашения __stdcall. Сразу вопрос: почему? И как мне указать соглашение о вызове в шаблоне, для данного компилятора?

Добавлено через 6 минут и 58 секунд
 smile В борланде по той же причине! Убираю соглашение, все проходит на ура. Но конкретизация специализации по соглашению мне в крайней степени нужна. Ваши предложения?
PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 20:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



Вообще почему бы не писать так?
Код

 template <class C, class R, class Func>
 class some
 {
 };


PM   Вверх
vaddsm
Дата 26.5.2009, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Потому как нужен не тип, а адрес метода. Вот, что интересно, в борланде радостно компилируется такой вариант:

Код

template <class R, class T0 , class T1 , class T2 , class T3>
class callback_cast<R __stdcall (*)( T0 , T1 , T2 , T3)>{};


А на MinGW, это Segmentation fault.

Добавлено через 8 минут и 51 секунду
Подитожу:

Код

template <class R, class T0 , class T1 , class T2 , class T3>
class callback_cast<R __stdcall (*)( T0 , T1 , T2 , T3)>
Borland      +
VC9.0         syntax error
MinGW        Segmentation fault

PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



Цитата(vaddsm @  26.5.2009,  20:17 Найти цитируемый пост)
template <class R, class T0 , class T1 , class T2 , class T3>
class callback_cast<R __stdcall (*)( T0 , T1 , T2 , T3)>{};

можно весь код посмотреть? непохоже на частичную специализацию.
PM   Вверх
vaddsm
Дата 26.5.2009, 21:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Для борланда думаю сделать так:

Код

#ifndef __BORLANDC__
#define CALLBACK_SPEC1 __stdcall
#define CALLBACK_SPEC2 
#else
#define CALLBACK_SPEC1 
#define CALLBACK_SPEC2 __stdcall
#endif

template <class R, class T0 , class T1 , class T2 , class T3>
class externalclass<R CALLBACK_SPEC2(CALLBACK_SPEC1 *)( T0 , T1 , T2 , T3)>{};


Да это не частичная специализация, прошу прощение за то что смутил, вот полный вариант с нистид классом где присутствует частичная специализация:

Код

template <typename R> class externalclass {};

template <class R, class T0 , class T1 , class T2 , class T3>
class externalclass<R CALLBACK_SPEC2(CALLBACK_SPEC1 *)( T0 , T1 , T2 , T3)>
{
public:
 typedef R  (__stdcall *call_back_type)( T0 , T1 , T2 , T3);
 template <class C, R (__stdcall C::*M)( T0 , T1 , T2 , T3)> class nested 
 {

 };
};
 

Borland      +
MinGW        -


Код

 //...

 template <class C, R (C::*M)( T0 , T1 , T2 , T3)> class nested {};

 //...

MinGW        +

При этом частичная специализация nested проходит в MinGW для всех типов соглашений (не только __cdecl), что весьма странно. 



Это сообщение отредактировал(а) vaddsm - 26.5.2009, 21:54
PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



vaddsm

Код

template <class C, class R, class Func>
class some
{
};

и все таки я бы сделал так.

Цитата(vaddsm @  26.5.2009,  21:46 Найти цитируемый пост)
Для борланда думаю сделать так:

а какой смысл в этих препроцессорах?

На MinGW завтра на работе гляну, дома нет.
PM   Вверх
vaddsm
Дата 26.5.2009, 21:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



В препроцессорах опечаточка была, подправил. 

Код

template <class C, class R, class Func>
class some
{
 // Тут  Func это ТИП.
}; 

template <class C, R (__stdcall C::*M)( T0 , T1 , T2 , T3)> class nested 
{
 // Здесь M это адрес - число.
};

PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 22:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



Цитата(vaddsm @  26.5.2009,  21:58 Найти цитируемый пост)
 // Здесь M это адрес - число.

брррр...совсем голова не варит smile не выспался.. smile

Добавлено @ 22:04
vaddsm

Нашел у себя Borland C++ Builder 6.

Код

#include <windows.h>
#include <iostream>

template <class C, void (__stdcall C::*M)()>
class nested
{
};

class A
{
public:
    void __stdcall foo()
    {
        std::cout << "hello world" << std::endl;
    }
};

int main()
{
    nested<A, &A::foo> d;
}


скомпилировал на ура.

Это сообщение отредактировал(а) azesmcar - 26.5.2009, 22:12
PM   Вверх
vaddsm
Дата 26.5.2009, 22:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Код

template <class C, void (__stdcall C::*M)()>
class nested
{
};

class A
{
   public: void __stdcall foo()
    {
     MessageBox(0,"good!","",0);
    }
};



на MingGW, строка 1: parse error before `)' token 

Код

template <class C, void __stdcall (C::*M)()>


Segmentation fault

Код

template <class C, void (C::*M)()>


ok

Добавлено через 3 минуты и 45 секунд
Причем последняя форма как я уже говорил принимает любое соглашение, и я теряюсь в догадках, каким образом, в таком вот случае, компилятор MinGW знает как именно в nested выполнить такой вот вызов:

(A_instanse->*M)();
PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 22:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



vaddsm

С Борландом разобрались?
PM   Вверх
vaddsm
Дата 26.5.2009, 22:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



MinGW лол: 

Код

class A
{
   public: void __fastcall foo(int a, int n)
    {
     MessageBox(0,"good!","",0);
    }    
};

template <class C, void (C::*M)(int, int)>
class nested
{
 public:nested()
 {
  A a;
  (a.*M)(1, 2); // Откуда друг ты мой любезный ты знаешь как вызвать M? Загадочный компилятор )
 }; 
};


Работает ))

Да, с борландом все на данный момент ок, в отличие от остальных компиляторов, он требует, указывать конвенцию вызова сразу после типа возвращаемого значения:
Код

<R __stdcall (*)( T0 , T1 , T2 , T3)>

при этом typedef указателя на такого рода функцию такой же как и везде:
Код

typedef R  (__stdcall *lpfn)( T0 , T1 , T2 , T3);

Не логично, как вы думаете?

Добавлено @ 22:36
Спасибо (+1) за ключ к разгадке! Но MinGW меня настораживает и вобще кто из компиляторов прав, я пересмотрел несколько раз стандарт, конкретики в данном вопросе не обнаружил (

Это сообщение отредактировал(а) vaddsm - 26.5.2009, 22:36
PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



vaddsm

Скачал MinGW, проверил
Код

#include <windows.h>
#include <iostream>

template <class C, void (__stdcall C::*M)()>
class nested
{
public:
    void call(C* that)
    {
        (that->*M)();
    }
};
class A
{
public:
    void __stdcall foo()
    {
        std::cout << "hello world" << std::endl;
    }
};
int main()
{
    nested<A, &A::foo> d;
    A t;
    d.call(&t);
}


работает..в чем проблема то?
PM   Вверх
vaddsm
Дата 26.5.2009, 22:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Пост выше. Проблема в том что работает ), серьезно. 
PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



Цитата(vaddsm @  26.5.2009,  22:34 Найти цитируемый пост)
Спасибо (+1) за ключ к разгадке! Но MinGW меня настораживает и вобще кто из компиляторов прав, я пересмотрел несколько раз стандарт, конкретики не обнаружил ( 

конкретики насчет чего? насчет __stdcall? Там ее и не будет, это Microsoft specific keyword.

Добавлено через 3 минуты и 24 секунды
Цитата(vaddsm @  26.5.2009,  22:37 Найти цитируемый пост)
Пост выше. Проблема в том что работает ), серьезно.  

А вызов? Обьект класса nested создается? если нет - то все нормально. Пока не используется шаблон - компилятор не генерирует его код. Если да - можно посмотреть как? может быть опять таки - все нормально.

Код

template <class T>
class V
{
 void f() {
 dfsl;jsdlfjsdfjsdfjdkljfkl
}
}


это тоже будет компилироватся - пока класс V не используется

Это сообщение отредактировал(а) azesmcar - 26.5.2009, 22:41
PM   Вверх
vaddsm
Дата 26.5.2009, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Так. У меня среда Dev. C++ (MinGW компиллер инсайд). На ваш код
Код

template <class C, void (__stdcall C::*M)()>

ругается матом parse error before `)' token.

Только так:
Код

template <class C, void (C::*M)()>



Затем. Я искал в стандарте информацию не о __stdcall в частности а об указании типов конвенций.

Добавлено через 2 минуты и 14 секунд
В моем примере я вызов делал также
Код

 nested<A, &A::foo> n;


И foo нормально вызывался, хотя не должен бы.
PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



Цитата(vaddsm @  26.5.2009,  22:51 Найти цитируемый пост)
Так. У меня среда Dev. C++ (MinGW компиллер инсайд). На ваш код

Очень очень странно
Код

#include <windows.h>
#include <iostream>
template <class C, void (__stdcall C::*M)()>
class nested
{
public:
    void call(C* that)
    {
        (that->*M)();
    }
};
class A
{
public:
    void __stdcall foo()
    {
        std::cout << "hello world" << std::endl;
    }
};
int main()
{
    nested<A, &A::foo> d;
    A t;
    d.call(&t);
}

вот этот код у меня скомпилировал
Цитата

gcc version 3.4.5 (mingw-vista special)

может скомпилятором что-то не так, попробуйте вручную, из командной строки.
Цитата

gcc file_name.cpp -lstdc++



Цитата(vaddsm @  26.5.2009,  22:51 Найти цитируемый пост)
И foo нормально вызывался, хотя не должен бы. 

почему? что ему мешает? попробуйте сгенерировать в уме тот код который сгенерирует компилятор для вашего шаблона, сразу станет понятно почему он работает.
PM   Вверх
vaddsm
Дата 26.5.2009, 23:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Цитата

почему? что ему мешает? попробуйте сгенерировать в уме тот код который сгенерирует компилятор для вашего шаблона, сразу станет понятно почему он работает.


По вполне, на мой взгляд, понятным причинам. Так как в нутри шаблона необходимо знать не только количество, типы параметров, возвращаяемое значение, но и то каким образом надо работать со стеком. В VS9.0 например такой вот шаблон template <class C, void (C::*M)()> вабще не примет __stdcall метод. Если не указывать явным образом соглашение, должно использоваться соглашение по умолчанию, в борланд в частности для void foo(); это __cdecl. 

Буду рад оказаться не правым ).

В Dev я наблюдаю несколько компиляторов mingw32-gcc.exe и gcc.exe. Сейчас проясню этот вопрос...

Добавлено через 10 минут и 16 секунд
bin>gcc -dumpversion
3.2

bin>gcc main2.cpp -lstdc++
main2.cpp:76: parse error before `)' token
...

bin>
PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 23:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



Цитата(vaddsm @  26.5.2009,  23:16 Найти цитируемый пост)

По вполне, на мой взгляд, понятным причинам. Так как в нутри шаблона необходимо знать не только количество, типы параметров, возвращаяемое значение, но и то каким образом надо работать со стеком. В VS9.0 например такой вот шаблон template <class C, void (C::*M)()> вабще не примет __stdcall метод. Если не указывать явным образом соглашение, должно использоваться соглашение по умолчанию, в борланд в частности для void foo(); это __cdecl. 

речь идет про __fastcall я так понял?

ну тут вы видимо ожидаете рантайм ошибки..так? потому что с точки зрения компилятора - все верно. У него через шаблоны передана функция - он ее вызывает. Единственное в чем он виноват - так в том что не выдал ошибку тут
Цитата

nested<A, &A::foo> n;

но...

по стандарту - нет ни __fastcall ни __stdcall. Это дополнения - которые к тому же не являются частью сигнатуры функции. Т.е. GCC не обязан проверять это.
Тогда вопрос - как же это не вылетает рантайм
Цитата

The __fastcall calling convention specifies that arguments to functions are to be passed in registers, when possible. The following list shows the implementation of this calling convention.

предполагаю что в данный момент это было not possible smile 
PM   Вверх
vaddsm
Дата 26.5.2009, 23:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



без __stdcall в шаблоне идет опять таки нормально
PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 23:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



Цитата

main2.cpp:76: parse error before `)' token

Листинг посмотреть можно?
76 строка, это явно не мой код smile тут есть изменения.
PM   Вверх
vaddsm
Дата 26.5.2009, 23:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



ВОТ ВОТ!!!! Я о том и твержу. Access violation быть просто обязан. Указал я __fastcall, чтобы нарочито заставить его обломаться, в том случае если он по умолчанию использует передачу параметров через стек а не регистры.

Загадки во тьме.....
PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



Цитата(vaddsm @  26.5.2009,  23:33 Найти цитируемый пост)
ВОТ ВОТ!!!! Я о том и твержу. Access violation быть просто обязан. Указал я __fastcall, чтобы нарочито заставить его обломаться, в том случае если он по умолчанию использует передачу параметров через стек а не регистры.

Загадки во тьме..... 

__fastcall 100% гарантии что параметры будут помещены в стек - не дает smile 
PM   Вверх
vaddsm
Дата 26.5.2009, 23:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



тотже:

Код

template <class C, void (__stdcall C::*M)()>

class nested
{
public:
    void call(C* that)
    {
        (that->*M)();
    }
};

class A
{
public:
    void __stdcall foo()
    {
    }
};

int main(int argc, char *argv[])
{

 nested<A, &A::foo> d;
 A t;
 d.call(&t);

 return 0;
 
}


cmd:

Цитата

D:\Program Files\DEVC\Dev-Cpp\bin>gcc main2.cpp -lstdc++
main2.cpp:1: parse error before `)' token
main2.cpp:13: definition of `class A' inside template parameter list
main2.cpp:16: can't make `foo' into a method -- not in a class
main2.cpp:18: declaration does not declare anything
main2.cpp:21: cannot declare `::main' to be a template
main2.cpp:21: confused by earlier errors, bailing out

D:\Program Files\DEVC\Dev-Cpp\bin>


Простите, а что у вас происходит без указания __stdcall в шаблоне, я могу поинтересоваться?
Нормально компилируется и так и так?

Цитата

__fastcall 100% гарантии...


я целый ряд различных соглашений задавал foo, fastcall часный случай. И все равно работает. 

PM MAIL   Вверх
azesmcar
Дата 26.5.2009, 23:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



vaddsm

Чем дальше - тем лучше smile 
Код

#include <windows.h>
#include <iostream>

void __fastcall f(int q, int v)
{
    std::cout << q << v;
}

typedef void (*f_ptr)(int, int);

int main()
{
    f_ptr p = f; //не компилирует minGW
    p(1, 2);
}

Цитата


test.cpp:13: error: invalid conversion from `void (*)(int, int)' to `void (*)(int, int)'

кажется вам пора обновляться

Добавлено через 2 минуты и 34 секунды
Цитата(vaddsm @  26.5.2009,  23:39 Найти цитируемый пост)
Простите, а что у вас происходит без указания __stdcall в шаблоне, я могу поинтересоваться?
Нормально компилируется и так и так?

Код который вы мне показали в последнем посте с ошибками
Цитата


D:\Program Files\DEVC\Dev-Cpp\bin>gcc main2.cpp -lstdc++
main2.cpp:1: parse error before `)' token
main2.cpp:13: definition of `class A' inside template parameter list
main2.cpp:16: can't make `foo' into a method -- not in a class
main2.cpp:18: declaration does not declare anything
main2.cpp:21: cannot declare `::main' to be a template
main2.cpp:21: confused by earlier errors, bailing out

D:\Program Files\DEVC\Dev-Cpp\bin>



у меня на MinGW прошел без ошибок.

Это сообщение отредактировал(а) azesmcar - 26.5.2009, 23:46
PM   Вверх
vaddsm
Дата 27.5.2009, 00:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Код

#include <windows.h>
#include <iostream>
void __fastcall f(int q, int v)
{
    std::cout << q << v;
}
typedef void (*f_ptr)(int, int);
int main()
{
    f_ptr p = f; //не компилирует minGW
    p(1, 2);
}


Ну да, почему в разетку пальцем лезть низя он понимает, даже у меня smile 

Цитата

у меня на MinGW прошел без ошибок.


Понятно, а тот же код но с таким изменением:
Код

template <class C, void (C::*M)()>
class nested
{
//...


Что говорит?

PM MAIL   Вверх
vaddsm
Дата 27.5.2009, 00:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



И всеже такой формы записи
Код

 template <class C, void (C::*M)()>
,
mingw'у вполне хватает чтобы в шаблоне знать тип соглашения о вызове. Проверил под отладчиком вызов метода foo декларированного с различными соглашениями:

Код

; вызов void __stdcall foo(int, int)

push   $0x2
push   $0x1
pushl  0xfffffffc(%ebp)      // this
call   *0xfffffff8(%ebp)


; вызов void __fastcall foo(int, int)

push   $0x2
mov    $0x1,%edx
mov    0xfffffffc(%ebp),%ecx // this
call   *0xfffffff8(%ebp)

; вызов void __cdecl foo(int, int)

push   $0x2
push   $0x1
pushl  0xfffffffc(%ebp) // this
call   *0xfffffff8(%ebp)



К чему я прихожу: Стандарт не определяет формат описания calling convetions в шаблонах? 


PM MAIL   Вверх
azesmcar
Дата 27.5.2009, 08:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



Цитата(vaddsm @  27.5.2009,  00:43 Найти цитируемый пост)
К чему я прихожу: Стандарт не определяет формат описания calling convetions в шаблонах? 

он вообще не определяет calling convetions. 

я думаю так:
__stdcall чисто микрософтовский кейворд и в GCC это по определению не было. Когда GCC портировали под виндоуз (minGW) __stdcall добавили. Возможно это бага старой версии.

Цитата(vaddsm @  27.5.2009,  00:04 Найти цитируемый пост)
Ну да, почему в разетку пальцем лезть низя он понимает, даже у меня smile 

ну мало ли..я думал там вообще с этим неполадки, если тут проверка работает, то почему не работает с шаблонами?

мое мнение: Хоть стандарт и не определяет поведение программы в таких случаях - при добавлении новых фич производители компиляторов должы добавить их так - чтобы они соответствовали общей структуре и логике ЯП. В конкретном случае логично то что он не позволяет компилироватся данной программе (у меня).

Код

#include <windows.h>
#include <iostream>

void __fastcall f(int q, int v)
{
    std::cout << q << v;
}

typedef void (*f_ptr)(int, int);

template <f_ptr fp>
void foo()
{
    fp(1, 2);
}

int main()
{
    foo<f>();
}

вот еще вариант с шаблонами. 
Цитата

test.cpp: In function `int main()':
test.cpp:19: error: no matching function for call to `foo()'

То что он компилует у вас - видимо просто бага - которую уже давно исправили smile обновите MinGW.

vaddsm

да..и еще..я бы с удовольствием взглянул на ассемблерный код сгенерированный для
Код

class A
{
   public: void __fastcall foo(int a, int n)
    {
     MessageBox(0,"good!","",0);
    }    
};
template <class C, void (C::*M)(int, int)>
class nested
{
 public:nested()
 {
  A a;
  (a.*M)(1, 2); // Откуда друг ты мой любезный ты знаешь как вызвать M? Загадочный компилятор )
 }; 
};

особенно интересует вот эта часть..
(a.*M)(1, 2);
тут эти два параметра push -ами идут в функцию или mov ecx ..., mov edx?
сам не могу..у меня не компилируется smile  smile 

Это сообщение отредактировал(а) azesmcar - 27.5.2009, 08:55
PM   Вверх
vaddsm
Дата 27.5.2009, 09:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



azesmcar, посмотри внимательнее, приведенный мною asm это как раз то о чем ты меня сейчас просишь, для 3х случаев когда 

Код

 public: void foo(int a, int n)
    {
     MessageBox(0,"good!","",0);
    }    


объявлена как __fastcall, __stdcall и __cdecl. Для случая с __fastcall первый параметр идет в edx, второй в стек.

Цитата

__stdcall чисто микрософтовский кейворд 


Да, но я говорю не о частном случае, естественно что описаний самих соглашений в стандарте нет. Меня интересует есть ли в стандарте чтолибо относительно формата указания информации об этих соглашениях в различных синтаксических ситуациях.

Добавлено через 1 минуту и 41 секунду
упс, прошу прощения за "Ты".

Добавлено через 5 минут и 33 секунды
Код

#include <windows.h>
#include <iostream>
void __fastcall f(int q, int v)
{
    std::cout << q << v;
}
typedef void (*f_ptr)(int, int);
template <f_ptr fp>
void foo()
{
    fp(1, 2);
}
int main()
{
    foo<f>();
}


Приведенный вами пример в mingw у меня не компилируется.

а вот то что компилится это:

Код


class A
{
   public: void __fastcall foo(int a, int n)
    {
     MessageBox(0,"good!","",0);
    }    
};
template <class C, void (C::*M)(int, int)>
class nested
{
 public:nested()
 {
  A a;
  (a.*M)(1, 2); // Откуда друг ты мой любезный ты знаешь как вызвать M? Загадочный компилятор )
 }; 
};


Действительно баг.

Добавлено через 6 минут и 48 секунд
Радует что в более поздних версиях его выпрямили.
PM MAIL   Вверх
azesmcar
Дата 27.5.2009, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



Цитата(vaddsm @  27.5.2009,  09:10 Найти цитируемый пост)
azesmcar, посмотри внимательнее, приведенный мною asm это как раз то о чем ты меня сейчас просишь, для 3х случаев когда 

да, ассемблер я увидел, но не совсем понял для какого он кода. Т.е. я думал это для обычного вызова написано а не для вызова через шаблон.
следовательно он понимает как ее вызывать smile 
ну, что тут скажешь..это компилятор, все в его руках smile фантастического во всяком случае ничего тут нет, в конце концов он знает какая ему функция была передана.


Цитата(vaddsm @  27.5.2009,  09:10 Найти цитируемый пост)

Да, но я говорю не о частном случае, естественно что описаний самих соглашений в стандарте нет. Меня интересует есть ли в стандарте чтолибо относительно формата указания информации об этих соглашениях в различных синтаксических ситуациях.


Цитата

The following conversions are performed on each expression used as a non-type template-argument. If a
non-type template-argument cannot be converted to the type of the corresponding template-parameter then
the program is ill-formed.

— for a non-type template-parameter of integral or enumeration type, integral promotions (4.5) and integral
conversions (4.7) are applied.

— for a non-type template-parameter of type pointer to object, qualification conversions (4.4) and the
array-to-pointer conversion (4.2) are applied. [Note: In particular, neither the null pointer conversion
(4.10) nor the derived-to-base conversion (4.10) are applied. Although 0 is a valid template-argument
for a non-type template-parameter of integral type, it is not a valid template-argument for a non-type
template-parameter of pointer type. ]

— For a non-type template-parameter of type reference to object, no conversions apply. The type referred
to by the reference may be more cv-qualified than the (otherwise identical) type of the templateargument.
The template-parameter is bound directly to the template-argument, which must be an
lvalue.

— For a non-type template-parameter of type pointer to function, only the function-to-pointer conversion
(4.3) is applied. If the template-argument represents a set of overloaded functions (or a pointer to such),
the matching function is selected from the set (13.4).


— For a non-type template-parameter of type reference to function, no conversions apply. If the
template-argument represents a set of overloaded functions, the matching function is selected from the
set (13.4).

— For a non-type template-parameter of type pointer to member function, no conversions apply. If the
template-argument represents a set of overloaded member functions, the matching member function is
selected from the set (13.4).


— For a non-type template-parameter of type pointer to data member, qualification conversions (4.4) are
applied.


Добавлено @ 09:28
Цитата(vaddsm @  27.5.2009,  09:10 Найти цитируемый пост)
упс, прошу прощения за "Ты".  

да без проблем smile 

Это сообщение отредактировал(а) azesmcar - 27.5.2009, 09:34
PM   Вверх
vaddsm
Дата 27.5.2009, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Для нетипового шаблонного параметра типа указатель на функцию, применяется только “функция к указателю (4.3)” конверсия. Если аргумент шаблона представлен множеством перегруженных функций (или указателем на таковые), то подходящая функция выбирается из множества. 

Для нетипового шаблонного параметра типа указатель на метод, конверсия не применяется. Если аргумент шаблона представлен множеством перегруженных методов (или указателем на таковые), то подходящий метод выбирается из множества. 


Конверсия != Конвенция 

Иными словами в приведенном фрагменте стандарта ничего не говорится о соглашених о вызовах.

Добавлено через 8 минут и 18 секунд
The C++ Standard [ISO/IEC 14882] has very little to say about calling conventions. It has a bit to say about language linkage and linkage specifications, and it notes that a particular language linkage may be associated with a particular calling convention. Everything else related to calling conventions is implementation specific.


Implementation specific для calling conventions, где бы найти  smile  smile ??
PM MAIL   Вверх
azesmcar
Дата 27.5.2009, 21:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



Цитата(vaddsm @  27.5.2009,  21:30 Найти цитируемый пост)
Иными словами в приведенном фрагменте стандарта ничего не говорится о соглашених о вызовах.

не только в приведенном фрагменте. Этот фрагмент касается non-type template-parameter-ов. smile 
т.е. это то что в стандарте сказано про передачу шаблонному классу/функции нетипового параметра.

Добавлено через 1 минуту и 53 секунды
Цитата(vaddsm @  27.5.2009,  21:30 Найти цитируемый пост)
Implementation specific для calling conventions, где бы найти  smile  smile ?? 

смотря для кого? smile 
если для студии - в MSDN, если для MinGW - то у них на сайте предполагаю что будет.

Добавлено через 4 минуты и 43 секунды
http://www.hackcraft.net/cpp/MSCallingConventions/

Это сообщение отредактировал(а) azesmcar - 27.5.2009, 21:41
PM   Вверх
vaddsm
Дата 27.5.2009, 22:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



Тот факт, что стандарт языка не регламентировал «Implementation specific of calling conventions» меня весьма удручает, ну что ж, все же это ответ на вопрос “Почему?”, хоть и отрицательный. 

На последок хочется взять и кинуть огромным булыжником в огород Borland. 

Апеллируя к вашим словам “при добавлении новых фич производители компиляторов должы добавить их так - чтобы они соответствовали общей структуре и логике ЯП”, с которыми я чертовски согласен, замечу: Что, разработчики компилятора Borland либо с нами не согласны либо сильно накасячили, заставив пользователей писать:

Код

template <class R, class T0>
class sometemplate<R __some_calling_convention (*)(T0)>
{
};


вместо волне логичного:

Код

template <class R, class T0>
class sometemplate<R  (__some_calling_convention *)(T0)>
{
};


PM MAIL   Вверх
azesmcar
Дата 27.5.2009, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 6
Всего: 211



vaddsm

надеетесь стать чемпионом по метанию камней в огород борланда? smile тут их каждый день кидают
что я говорю...я же в разделе Borland C++ Builder
но он в самом деле весьма сомнительно поддерживает стандарт, хотя получше чем Visual Studio 6. Но не будем забывать сколько лет дедушке.
PM   Вверх
vaddsm
  Дата 27.5.2009, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



 smile еще один фейл Борланда:


Код

  template < typename T, T*(T::*)() > struct ptmf_helper {};
  template < typename T > bool has_user_constructor_helper(...);
  template < typename T > bool has_user_constructor_helper(ptmf_helper<T, &T::Constructor>* p);


Heeelp me!!! )
PM MAIL   Вверх
vaddsm
Дата 28.5.2009, 10:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

Репутация: нет
Всего: нет



boost::enable_if так же не работает на 6.0. Вероятно по причине того что принцип substitution-failure-is-not-an-error в компиляторе не реализован (. Придется мне видимо отказаться от некоторых замечательных вещей ради совместимости. Но если вдруг у кого-то будет идея как заставить последний ряд шаблонов работать на этом компиляторе.... Буду ОЧЕНЬ рад.
PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

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

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.1003 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.