模板方法何时可以使用以后定义的函数而无需前向声明? [英] When can a template method use a function defined later, without forward declaration?

查看:58
本文介绍了模板方法何时可以使用以后定义的函数而无需前向声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个类似于QDebug的简单记录器类,该类具有将数据保存到QStringList中的模板方法.代码在这里:

I am writing a simple logger class similar to QDebug, which has a template method that save data into QStringList. The code is here:

#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QTextStream>

class Logger
{
    public:
        Logger();

        ~Logger();

        template <typename V>
        Logger &operator<<(V const &value);

    private:
        QStringList msg;
};

inline Logger::Logger():
    msg(QString("INFO:"))
{}

inline Logger::~Logger()
{
    QTextStream out(stderr);
    out << msg.join("");
}

template <typename V>
inline Logger &Logger::operator<<(V const &value)
{
    msg << log(value);
    return *this;
}

inline QString log(QString const &value)
{
    return value;
}

inline QString log(int const (&value)[20])
{
    return QString("Array");
}

int main(int argc, char *argv[])
{
    Logger c;
    int a[20] = {};
    c << QString("test") << a;

    return 0;
}

但是,它不能与GCC 4.8.3一起编译.

However, this doesn't compile with GCC 4.8.3.

$ g++ -I/usr/include/qt4 -L/usr/lib64/qt4 -lQtCore -o test2 test2.cpp
test2.cpp: In instantiation of ‘Logger& Logger::operator<<(const V&) [with V = int [20]]’:
test2.cpp:50:29:   required from here
test2.cpp:32:21: error: ‘log’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
     msg << log(value);
                     ^
test2.cpp:41:16: note: ‘QString log(const int (&)[20])’ declared here, later in the translation unit
 inline QString log(int const (&value)[20])

实际上,如果我将 inline QString log(int const(& value)[20])移到开头或放入前向声明,它将编译并起作用.但是令我困惑的是,内联QString日志(QString const& value)可以正常工作:

Indeed, if I move inline QString log(int const (&value)[20]) to the beginning or put a forward declaration, it compiles and works. But what confuses me is that inline QString log(QString const &value) works without any problem:

$ ./test2
INFO:testArray

我注意到QHash依赖于qHash函数,这种情况下类似.QHash可与用户定义的键类(数组除外,不能是函数返回类型)一起很好地工作.

I notice that QHash relies on qHash function, which is similar in this case. QHash works pretty fine with user-defined key classes (except arrays, which can't be a function return type).

为什么他们的行为有所不同?我在这里想念什么?

Why do they behave differently? What did I miss here?

谢谢您的帮助.

顺便说一句:您能告诉我什么是解决这个问题的好关键字.我已经尝试过将专业",模板",转发声明","QHash"和用户定义的类型"组合使用,但是它们不起作用.

BTW: Would you please tell me what would be good keywords for this question. I've tried combinations of "specialiation" "template" "forward declaration" "QHash" and "user-defined types", but they don't work.

推荐答案

名称 log 被查询了两次.在模板定义时,将执行普通查找.它找不到任何东西,因为此时未声明 log .

The name log is looked up twice. At the point of template definition, ordinary lookup is performed. It doesn't find anything, since log is not declared at this point.

然后,在实例化时,仅执行依赖于参数的查找.当参数的类型为 QString 时,由于在其中声明了 QString ,因此将搜索全局名称空间,因此将找到 log(QString).但是类型 int [] 没有任何关联的名称空间,因此依赖于参数的查找没有要搜索的内容,也没有找到任何内容.因此是错误.

Then, at the point of instantiation, only argument-dependent lookup is performed. When the parameter is of type QString, the global namespace is searched since QString is declared there, and so log(QString) is found. But the type int[] doesn't have any associated namespaces, so argument-dependent lookup has nothing to search and finds nothing. Hence the error.

这篇关于模板方法何时可以使用以后定义的函数而无需前向声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆