何时模板方法可以使用稍后定义的函数,而无需前向声明?

时间:2014-07-26 04:47:02

标签: c++ qt templates

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

#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编译的。

$ 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])移到开头或提出前瞻性声明,它就会编译并运作。但令我困惑的是inline QString log(QString const &value)没有任何问题:

$ ./test2
INFO:testArray

我注意到QHash依赖于qHash函数,在这种情况下类似。 QHash与用户定义的密钥类(数组除外,它不能作为函数返回类型)工作得很好。

他们为什么表现不一样?我在这里想念的是什么?

感谢您的帮助。

顺便说一句:请你告诉我这个问题的好关键词。我尝试过&#34; specialiation&#34;的组合。 &#34;模板&#34; &#34;转发声明&#34; &#34; QHash&#34;和&#34;用户定义的类型&#34;,但它们不起作用。

1 个答案:

答案 0 :(得分:1)

名称log被查找两次。在模板定义时,执行普通查找。它没有找到任何内容,因为此时未声明log

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