expression as template parameter
От: dik o-braz  
Дата: 17.12.03 06:41
Оценка:
Господа, всем доброе время суток!
На следующую программку из двух строк VC++ 6.0 SP6
выругался следующим образом:
C2964 — invalid expression as template parameter
Так вот вопрос такой: это он зачем так ? И согласен ли
с ним Стандарт в этом случае ?

template<void *V> class T {};
T<(void *)1> t; // <- здесь
Re: expression as template parameter
От: dik o-braz  
Дата: 17.12.03 06:48
Оценка:
Виноват, vc++ 6.0 sp5, конечно же
Re: expression as template parameter
От: Павел Кузнецов  
Дата: 17.12.03 08:53
Оценка:
Здравствуйте, dik, Вы писали:

do> C2964 — invalid expression as template parameter

do> Так вот вопрос такой: это он зачем так ?
do> И согласен ли с ним Стандарт в этом случае ?
do> template<void *V> class T {};
do> T<(void *)1> t; // <- здесь

Все верно: в качестве нетипового аргумента шаблона — указателя стандарт разрешает только
адреса объектов или функций с внешним связыванием. Вот полный перечень того, что может служить
в качестве нетиповых аргументов шаблонов:

14.3.2/1

A template-argument for a non-type, non-template template-parameter shall be one of:
— an integral constant-expression of integral or enumeration type; or
— the name of a non-type template-parameter; or
— the name of an object or function with external linkage, including function templates and function
template-ids but excluding non-static class members, expressed as id-expression; or
— the address of an object or function with external linkage, including function templates and function
template-ids but excluding non-static class members, expressed as & id-expression where the & is
optional if the name refers to a function or array; or
— a pointer to member expressed as described in 5.3.1.

Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: expression as template parameter
От: achp  
Дата: 17.12.03 09:03
Оценка:
Здравствуйте, dik o-braz, Вы писали:

DOB>template<void *V> class T {};
DOB>T<(void *)1> t; // <- здесь


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

Например:

template<void *V> class T {};

extern X x;

T<&x> t;
Да здравствует ИМХО!
Re: expression as template parameter
От: Кодт Россия  
Дата: 17.12.03 09:03
Оценка:
Здравствуйте, dik o-braz, Вы писали:

DOB>template<void *V> class T {};
DOB>T<(void *)1> t; // <- здесь


А так не пробовал? Может, это более осмысленно, чем передавать инвалидные указатели?
template<int n> class T {};
T<1> t;
Перекуём баги на фичи!
Re[2]: expression as template parameter
От: dik o-braz  
Дата: 17.12.03 09:13
Оценка:
ПК>Все верно: в качестве нетипового аргумента шаблона — указателя стандарт разрешает только
ПК>адреса объектов или функций с внешним связыванием. Вот полный перечень того, что может служить
ПК>в качестве нетиповых аргументов шаблонов:

Спасибо.
Тогда, насколько я понимаю, код

template<void *V> class T {};
T<(void *)0> t;

тоже не является корректным. Хотя воспринимается вц++ 6
без вопросов
Re[2]: expression as template parameter
От: dik o-braz  
Дата: 17.12.03 09:25
Оценка:
К>А так не пробовал? Может, это более осмысленно, чем передавать инвалидные указатели?
К>
К>template<int n> class T {};
T<1>> t;
К>


Объясню смысл: пытаюсь завернуть виндовый HANDLE в шаблон, в
качестве одного из параметров которого должно участвовать
его неправильное значение (NULL или INVALID_HANDLE_VALUE).
Но на значении параметра INVALID_HANDLE_VALUE суть которого
(HANDLE *)-1 вц++ обломился в отличие от NULL
Re[3]: expression as template parameter
От: achp  
Дата: 17.12.03 09:26
Оценка:
Здравствуйте, dik o-braz, Вы писали:

DOB>Объясню смысл: пытаюсь завернуть виндовый HANDLE в шаблон...


Ну-ка, ну-ка... Очень интересно!
Да здравствует ИМХО!
Re[3]: expression as template parameter
От: Кодт Россия  
Дата: 17.12.03 09:35
Оценка:
Здравствуйте, dik o-braz, Вы писали:

DOB>Объясню смысл: пытаюсь завернуть виндовый HANDLE в шаблон, в

DOB>качестве одного из параметров которого должно участвовать
DOB>его неправильное значение (NULL или INVALID_HANDLE_VALUE).
DOB>Но на значении параметра INVALID_HANDLE_VALUE суть которого
DOB>(HANDLE *)-1 вц++ обломился в отличие от NULL

Сомнительная затея. Все значения хэндлов, кроме NULL и INVALID_HANDLE_VALUE, не являются константами времени компиляции. Их раздает операционная система, более или менее произвольным образом.
Перекуём баги на фичи!
Re[3]: expression as template parameter
От: Павел Кузнецов  
Дата: 17.12.03 09:42
Оценка:
Здравствуйте, dik, Вы писали:

ПК>> в качестве нетипового аргумента шаблона — указателя стандарт разрешает только

ПК>> адреса объектов или функций с внешним связыванием.

do> Тогда, насколько я понимаю, код

do> template<void *V> class T {};
do> T<(void *)0> t;
do> тоже не является корректным.

Верно. GCC, например, говорит так:
test.cpp:2: `0' is not a valid template argument
test.cpp:2: it must be the address of an object with external linkage

и имеет право.

do> Хотя воспринимается вц++ 6 без вопросов


Это распространенное расширение, поддерживаемое многими компиляторами. По этому
поводу есть предложение разрешить нулевые указатели в качестве нетиповых аргументов
шаблонов: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#354
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: expression as template parameter
От: dik o-braz  
Дата: 17.12.03 09:44
Оценка:
Короче, стоит задача обобщения представления
простых свойств WIN32-типа HANDLE, представляющего
различные объекты системы: файлы, события, мьютексы и т.п.
В простом варианте это обобщение собиралось выглядеть так:

template<BOOL (WINAPI *Clo)(HANDLE), HANDLE Inv> class handle_t {
    HANDLE    _h;
public:
    handle_t(): _h(Inv) {}
    // ...
    virtual ~handle_t() { close(); }

    handle_t &operator = (HANDLE h)
    {
        close(); _h = h;
    }
 
    operator HANDLE() const { return _h; }

    void close()
    {
        if( Inv != _h ) {
            Clo( _h );
            _h = Inv;
        }
    }
};
typedef handle_t<CloseHandle, INVALID_HANDLE_VALUE> file_handle_t;
typedef handle_t<CloseHandle, NULL> event_handle_t;
typedef handle_t<FindClose, INVALID_HANDLE_VALUE> notif_handle_t;
//...


Но вот пока не срослось со вторым параметром ...
Re[4]: expression as template parameter
От: dik o-braz  
Дата: 17.12.03 09:48
Оценка:
К>Сомнительная затея. Все значения хэндлов, кроме NULL и INVALID_HANDLE_VALUE, не являются константами времени компиляции. Их раздает операционная система, более или менее произвольным образом.

Все это понятно. Мне как раз и нужны всего две константы
Re[5]: expression as template parameter
От: WeCom Беларусь  
Дата: 17.12.03 10:11
Оценка:
Здравствуйте, dik o-braz, Вы писали:

К>>Сомнительная затея. Все значения хэндлов, кроме NULL и INVALID_HANDLE_VALUE, не являются константами времени компиляции. Их раздает операционная система, более или менее произвольным образом.


DOB>Все это понятно. Мне как раз и нужны всего две константы


Запакуй их в структуру и передавай вторым параметром шаблона тип соответствующей структуры.
Re[5]: expression as template parameter
От: Павел Кузнецов  
Дата: 17.12.03 10:13
Оценка: 3 (1)
Здравствуйте, dik, Вы писали:

do> В простом варианте это обобщение собиралось выглядеть так:

do>
 do> template<BOOL (WINAPI *Clo)(HANDLE), HANDLE Inv> class handle_t {
 do>  HANDLE _h;
 do> public:
 do>  handle_t(): _h(Inv) {}
 do>  // ...

 do>  void close()
 do>  {
 do>   if( Inv != _h ) {
 do>    Clo( _h );
 do>    _h = Inv;
 do>   }
 do>  }
 do> };
 do> typedef handle_t<CloseHandle, INVALID_HANDLE_VALUE> file_handle_t;
 do> typedef handle_t<CloseHandle, NULL> event_handle_t;
 do> typedef handle_t<FindClose, INVALID_HANDLE_VALUE> notif_handle_t;
 do> //...
 do>


do> Но вот пока не срослось со вторым параметром ...


Это несложно поправить: насколько я вижу, у тебя нет никакой необходимости в том, чтобы параметр
Inv передавался именно так. Предлагаю сделать передавать его косвенно, посредством стратегией/policy.
struct InvalidHandleValue
{
  static HANDLE inv() { return INVALID_HANDLE_VALUE; }
};

struct NullHandle
{
  static HANDLE inv() { return NULL; }
};

template<BOOL (WINAPI *Clo)(HANDLE), class InvPolicy>
class handle_t {
 HANDLE _h;
public:
 handle_t(): _h(InvPolicy::inv()) {}
 // ...
};


Если есть желание, можно даже объединить оба аргумента в единую стратегию/policy:
template<class Policy>
class handle_t {
  . . .

это позволит не быть привязанным к конкретному типу функции, освобождающей хэндл, достаточно будет,
что в структуре, задаваемой параметром Policy будет статическая функция close() принимающая в качестве
аргумента HANDLE.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[6]: expression as template parameter
От: WeCom Беларусь  
Дата: 17.12.03 10:17
Оценка:
Здравствуйте, WeCom, Вы писали:

WC>Запакуй их в структуру и передавай вторым параметром шаблона тип соответствующей структуры.



struct NULL_st 
{ 
static HANDLE get_invalid() { return NULL; } 
};

struct INV_HANDLE_st 
{ 
static HANDLE get_invalid() { return INVALID_HANDLE_VALUE; } 
};

template<BOOL (WINAPI *Clo)(HANDLE), class T Inv> class handle_t {
    HANDLE    _h;
public:
    handle_t() {}
    // ...
    virtual ~handle_t() { close(); }

    handle_t &operator = (HANDLE h)
    {
        close(); _h = h;
    }
 
    operator HANDLE() const { return _h; }

    void close()
    {
        if( Inv::get_invalid() != _h ) {
            Clo( _h );
            _h = Inv::get_invalid();
        }
    }
};
typedef handle_t<CloseHandle, INV_HANDLE_st> file_handle_t;
typedef handle_t<CloseHandle, NULL_st> event_handle_t;
typedef handle_t<FindClose, INV_HANDLE_st> notif_handle_t;
Re[6]: expression as template parameter
От: dik o-braz  
Дата: 17.12.03 11:12
Оценка:
ПК>Это несложно поправить: насколько я вижу, у тебя нет никакой необходимости в том, чтобы параметр
ПК>Inv передавался именно так.

Верно.

ПК>Предлагаю сделать передавать его косвенно, посредством стратегией/policy.


Видимо, так и придется сделать. Спасибо.
Думается, такое ограничение для параметров шаблона — указателей ввели для
того, чтобы уберечься от испоьзования его возможно неинициализированного
значения.
Re[7]: expression as template parameter
От: achp  
Дата: 17.12.03 11:14
Оценка: +1
Здравствуйте, dik o-braz, Вы писали:

DOB>Видимо, так и придется сделать. Спасибо.

DOB>Думается, такое ограничение для параметров шаблона — указателей ввели для
DOB>того, чтобы уберечься от испоьзования его возможно неинициализированного
DOB>значения.

Нет, для того, чтобы упростить работу сборщику — ведь получающиеся из шаблонов классы и функции нужно как-то идентифицировать.
Да здравствует ИМХО!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.