Вопрос

template<typename T> struct A {
    auto func() -> decltype(T::func()) {
        return T::func();
    }
};
class B : public A<B> {
    void func() {
    }
};

Кажется, довольно просто для меня. Но MSVC не может компилировать.

visual studio 2010\projects\temp\temp\main.cpp(4): error C2039: 'func' : is not a member of 'B'
visual studio 2010\projects\temp\temp\main.cpp(8) : see declaration of 'B'
visual studio 2010\projects\temp\temp\main.cpp(8) : see reference to class template instantiation 'A<T>' being compiled
          with
          [
              T=B
          ]
visual studio 2010\projects\temp\temp\main.cpp(4): error C3861: 'func': identifier not found

Несмотря на то, что компилятор радостно примет, вызывая функцию. Приведенный ниже образца компилируется нормально.

template<typename T> struct A {
    void func() {
        return T::func();
    }
};
class B : public A<B> {
    void func() {
    }
};

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

template<typename T> struct A {
    typedef typename T::something something;
};
class B : public A<B> {
    typedef char something;
};

visual studio 2010\projects\temp\temp\main.cpp(4): error C2039: 'something' : is not a member of 'B'

Тогда как класс B четко определяет тип называемый «что-то». Компилятор идеально рад вызывать функции на объекте типа T, T & или T *, но я не могу получить доступ к любым типам из T.

Это было полезно?

Решение

Вы пытаетесь использовать T::func до того, как он был объявлен. Вот почему компилятор кричит на вас. Обратите внимание, что когда вы получаете из класса, класс генерируется, если он исходит от шаблона класса. И неявное поколение класса (которое называется неявной инстанцией) требует генерации деклараций для всех его членов (поэтому компилятор знает значение в размере класса и может выполнить поиск в него).

Так что это также создает признательности декларации auto func() -> decltype(T::func()) И наверняка не удается здесь.

Другие советы

Кажется, есть несколько проблем с вашим кодом, один из которых выглядит как ошибка VS10.

  1. Вы звонили T::func() от A без литья A к T, это необходимо как часть CRPT с момента A не происходит от T. Отказ - fixl. return static_cast<T*>(this)->func();
  2. Чем вы передаете decltype выглядит как статическая вызов функции в то время как func на самом деле функция экземпляра. С decltype нет на самом деле запустить функцию, которую вы должны сделать что-то вроде этого decltype(static_cast<T*>(nullptr)->func())
  3. func является частным в B и не может быть вызван от A - Исправить: изменить A быть struct
  4. Это похоже на ошибку в VS10, даже после всех этих исправлений я получаю ошибку, которую вы пытаетесь использовать неопределенный класс B в decltype.

Как обходной путь вы можете рефакторировать func в базовый класс? (Теперь нам нужны два параметра шаблона, один для литья до одного для decltype Таким образом, создание нового IDIOM CRTPEX)

struct Base { 
    void func() { }
};

template<typename T, typename U> struct A {
    auto func() -> decltype(static_cast<T*>(nullptr)->func()) {
        return static_cast<U*>(this)->func();
    }
};


struct B : public A<Base, B>, public Base {
};

Я вижу, что G ++ также задыхается на этом decltype Может кто-нибудь подтвердить, что это дефект? Если так, я открою ошибку для Microsoft. Я понимаю, что следующий код действителен, но ни G ++, ни VC10 не компилируют его.

template<typename T> struct A {
    auto func() -> decltype(static_cast<T*>(nullptr)->func()) {
        return static_cast<T*>(this)->func();
    }
};

struct B : public A<B> {
    void func() {}
};

Во-первых, я думаю, что код рядом - правильный:

template<typename T> struct A {
    auto func()
     -> decltype(static_cast<T*>(this)->func()) 
    {
        return static_cast<T*>(this)->func();
    }
};
class B : public A<B> {
    void func(){
    }
};

Как отметил Мотти. Однако это Все еще не удается, и я думаю по причине, что возвратный тип базы должен быть известен, когда B наследуется от A<B>, но с тех пор B Это еще не определено, это становится проблемой курицы и яйца.

Тем не менее, может быть, наконец возможен в C++1y Используя просто auto (без decltype), Я пытался с gcc-4.8.2

template<typename T> struct A {
    auto func()
    //c++1y// -> decltype(static_cast<T*>(this)->func()) 
    {
        return static_cast<T*>(this)->func();
    }
};
class B : public A<B> {
    void func(){
    }
};

Это компилирует (c++ -std=c++1y) и работает:

int main(){
  B b; b.func();
}

Два отказ от ответственности: я не знаю, почему это работает. Я не знаю, насколько это стандартно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top