Добавление другого параметра в класс делает код некомпилируемым - PullRequest
0 голосов
/ 05 декабря 2018

Я создал класс, расширяющий коллекцию map-of-handlers, которая выполняет некоторые задачи в соответствии с рефлексивными аргументами (это попытка сделать отражение для c ++).Однако когда я настроил его, чтобы он не был привязан к конкретной реализации, компилятор отказался работать, показав странную ошибку.Короче говоря, это компилируется:

using namespace std;

template<class T>
class Blah {
public:
    using ctx_t = map<T, string>;

private:
    map<string, function<void(ctx_t&)>> handlers;

protected:
    void registerHandler(const string& name, function<void(ctx_t&)> fn) {
        handlers[name] = fn;
    }
};

class BlahDescendant : public Blah<string> {
public:
    BlahDescendant() {
        registerHandler("ala", [](ctx_t& m) {cout << m["ala"]; });
    }
};

int main() {
    BlahDescendant desc;
    return 0;
}

Но при параметризации он отказывается компилировать, говоря, что

testfield.cpp:33:35: error: 'ctx_t' has not been declared

.

using namespace std;

template<class T, class X>
class Blah {
public:
    using ctx_t = map<T, X>;

private:
    map<string, function<void(ctx_t&)>> handlers;

protected:
    void registerHandler(const string& name, function<void(ctx_t&)> fn) {
        handlers[name] = fn;
    }
};

template<class X>
class BlahDescendant : public Blah<string, X> {
public:
    BlahDescendant() {
        registerHandler("ala", [](ctx_t& m) {cout << m["ala"]; });
    }
};

int main() {
    BlahDescendant<string> desc;
    return 0;
}

При попытке датьНа карте в лямбдах есть другая ошибка:

error: 'registerHandler' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
     registerHandler("ala", [](map<string,X>& m) {cout << m["ala"]; });

Кто-нибудь может помочь?

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

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

Итак, вы должны сообщить компилятору, что ваш тип ctx_t от Blah, поэтому вам нужно либо

[](typename Blah<string,X>::ctx_t& m) {cout << m["ala"]; }

или

template<class X>
class BlahDescendant : public Blah<string, X> {
public:
    using ctx_t = typename Blah<string,X>::ctx_t;
};

registerHandler также не является зависимым именем, поэтому необходимо сделать его зависимым от областей BlahDescendant и Blah, используя this явно

template<class X>
class BlahDescendant : public Blah<string, X> {
public:
    using ctx_t = typename Blah<string,X>::ctx_t;
    BlahDescendant() {
         this->registerHandler("ala", [](ctx_t& m) {cout << m["ala"]; });
    }
};
0 голосов
/ 05 декабря 2018
BlahDescendant() {
    this->registerHandler("ala", [](auto& m) {cout << m["ala"]; });
}

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

Если вы хотите явно ввести эту лямбду, вам нужно typename, так кактип определяется в шаблоне класса:

[](typename Blah<string, X>::ctx_t& m) { ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...