C2447 при использовании фигурных скобок для шаблонной инициализации базового класса в шаблонном классе - PullRequest
0 голосов
/ 07 февраля 2019

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

Библиотекав основном разрабатывается на Linux с использованием gcc, но стремится к кросс-платформенной совместимости и в моем случае используется на Windows с использованием Visual Studio 2015.

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

#include <iostream>

template <typename T>
class A
{
public:
    A(T x);
    virtual ~A() = default;
    T getX();
private:
    T x;
};

template <typename T>
class B : public A<T>
{
public:
    B(T x);
};

template <typename T>
class C : public A<T>
{
public:
    C(T x);
};

template <typename T>
class D : public A<T>
{
public:
    D(T x);
};


int main(int argn, char** argc)
{
    A<int> a(42);
    B<int> b(42);
    C<int> c(42);
    D<int> d(42);
    std::cout << "A: " << a.getX() << std::endl
        << "B: " << b.getX() << std::endl
        << "C: " << c.getX() << std::endl
        << "D: " << d.getX() << std::endl;
    return 0;
}

template<typename T>
A<T>::A(T x) : x(x) {}

template<typename T>
T A<T>::getX() { return x; }

template<typename T>
B<T>::B(T x) : A{ x / 2 } {} // does not compile in gcc [1]

template<typename T>
C<T>::C(T x) : A<T>(x * 2) {} // compiles fine in both

template<typename T>
D<T>::D(T x) : A<T>{ x*x } {} // does not compile in MSVC 2015 [2]

/*
[1]: error: class 'B<T>' does not have any field named 'A'
     B<T>::B(T x) : A{ x / 2 } {}

[2]: error C2447: '{': missing function header (old-style formal list?)
*/

Мой онлайн-поиск, чтобы выяснить, является ли это ошибкой компилятора или это неверная запись в соответствии со стандартом, осталась бесплодной.Кто-нибудь может объяснить, какие обозначения, используемые в B, C и D, следует считать правильными?Очевидно, что оба компилятора согласны с C, но наивно я считаю, что обозначения, используемые в B и D, также верны.

1 Ответ

0 голосов
/ 07 февраля 2019

В нотации B (ниже) в шаблоне базового класса A отсутствует параметр шаблона (к нему относится конструктор A), поэтому GCC (и Clang также) не могут его скомпилировать.

template<typename T>
B<T>::B(T x) : A{ x / 2 } {} // does not compile in gcc [1]

Изменение, как это работает.

template<typename T>
B<T>::B(T x) : A<T>{ x / 2 } {} // does not compile in gcc [1]

В случае обозначения D, GCC (и Clang также верны), потому что есть соответствующий конструктор для инициализации A<int>.MSVC не прав, чтобы отклонить его.

...