向该类添加另一个参数使代码无法编译

时间:2018-12-05 13:29:19

标签: c++ c++11

我创建了一个类,该类扩展了handle-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;
}

当尝试在lambdas中提供地图时,报告了不同的错误:

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 :(得分:2)

在类模板或类模板的成员的定义中,如果类模板的基类依赖于模板参数,则在定义时也不会在非限定名称查找期间检查基类范围类模板或成员的实例化或在类模板或成员的实例化过程中。

因此,您需要告诉编译器,您的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也是非依赖名称,因此您需要使用 this

明确使其依赖于BlahDescendant和Blah范围。
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"]; });
    }
};

答案 1 :(得分:0)

BlahDescendant() {
    this->registerHandler("ala", [](auto& m) {cout << m["ala"]; });
}

访问模板类的基类的成员时,需要显式使用this->

如果要显式键入该lambda,则需要typename,因为该类型是在类模板中定义的:

[](typename Blah<string, X>::ctx_t& m) { ...