Почему я не могу уменьшить указатель на элементы в аргументах шаблона? - PullRequest
5 голосов
/ 26 октября 2010

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

struct Foo
{
    int x;
};

struct Bar : public Foo
{
};

template<class T, int T::* z>
struct Buzz
{
};

static int Bar::* const workaround = &Foo::x;

int main()
{
    // This works. Downcasting of pointer to members in general is fine.
    int Bar::* y = &Foo::x;

    // But this doesn't, at least in G++ 4.2 or Sun C++ 5.9. Why not?
    // Error: could not convert template argument '&Foo::x' to 'int Bar::*'
    Buzz<Bar, &Foo::x> test;

    // Sun C++ 5.9 accepts this but G++ doesn't because '&' can't appear in
    // a constant expression
    Buzz<Bar, static_cast<int Bar::*>(&Foo::x)> test;

    // Sun C++ 5.9 accepts this as well, but G++ complains "workaround cannot
    // appear in a constant expression"
    Buzz<Bar, workaround> test;

    return 0;
}

1 Ответ

5 голосов
/ 26 октября 2010

Это просто не разрешено. Согласно §14.3.2 / 5:

Следующие преобразования выполняются для каждого выражения, используемого в качестве нетипового аргумента шаблона. Если нетипизированный шаблонный аргумент не может быть преобразован в тип соответствующего шаблонного параметра, то программа некорректна.
- для нетипового шаблона-параметра интегрального или перечислимого типа применяются интегральные продвижения (4.5) и интегральные преобразования (4.7).
- для нетипового шаблона-параметра типа указатель на объект применяются квалификационные преобразования (4.4) и преобразование массива в указатель (4.2). - Для нетипового шаблона-параметра типа ссылка на объект преобразования не применяются. Тип, на который ссылается ссылка, может быть более квалифицированным по cv, чем (иначе идентичный) тип аргумента шаблона. Параметр шаблона напрямую связан с аргументом шаблона, который должен быть lvalue.
- Для нетипового шаблона-параметра типа указатель на функцию применяется только преобразование функции в указатель (4.3). Если аргумент шаблона представляет собой набор перегруженных функций (или указатель на них), соответствующая функция выбирается из набора (13.4).
- Для нетипового шаблона-параметра типа ссылки на функцию преобразования не применяются. Если аргумент шаблона представляет собой набор перегруженных функций, соответствующая функция выбирается из набора (13.4).
- Для нетипового шаблона-параметра указателя типа на функцию-член преобразования не применяются. Если аргумент шаблона представляет собой набор перегруженных функций-членов, соответствующая функция-член выбирается из набора (13.4).
- Для нетипового шаблона-параметра указателя типа на элемент данных применяются квалификационные преобразования (4.4).

Я подчеркнул преобразование в отношении указателя на элементы данных. Обратите внимание, что ваше преобразование (§4.11 / 2) не указано в списке. В C ++ 0x это остается тем же самым в этом отношении.

...