编译器无法推断出哪种模板类型 return

Compiler cannot deduce which template type to return

相关代码是:

std::fstream fout("Logs.txt");
class Logs;
typedef std::ostream& (*ostream_manipulator2)(std::ostream&);
class LogsOutput
{
public:
    LogsOutput() {}
    ~LogsOutput() {}
    Logs * pLogs;
    friend LogsOutput& operator<<(LogsOutput &logsClass, std::string &strArg);
    friend LogsOutput& operator<<(LogsOutput &logsClass, const char *strArg);
    friend LogsOutput& operator<<(LogsOutput &logsClass, ostream_manipulator2 pf);
    friend LogsOutput& operator<<(LogsOutput &logsClass, uint64_t number);
};
LogsOutput *pLogsOutput;  
template <typename T>  
T& LOUToutput()
{
                    if (pLogsOutput)
                    {
                        return (*pLogsOutput);
                    }
                    else
                        return fout;
}

我想这样调用这个函数:

LOUToutput () << "Print this line " << std::endl;

但有时 LogsOutput class 不会创建,因此取消引用其指针会崩溃,在这种情况下我宁愿输出到文件。 我知道编译器无法在编译时判断 LogsOutput class 是否会被实例化,因此无法推断出模板的类型,但我看不出有任何其他方法可以做到工作。 所以我的问题是我的函数 return 如何根据 运行 时间条件成为不同的类型?

对此的复杂解决方案是使用继承。如果你要从 std::ostream 继承,你可以 return 一个共同的基础 class (如果你有兴趣,这里是一个讨论:How to inherit from std::ostream?

在我看来,更简单的解决方案是 return 一个代理 class,根据需要重定向输出。

struct LogProxy {
    LogsOutput *pLog;
    // ...
    LogProxy &operator<<(std::string &o) {
       if(pLogsOutput) {
          *pLog << o;
       } else {
          // Assuming this is available as a global.. You probably don't want to do that
          fout << o;
       }
       return *this;
    }
    // ....
};

LogProxy LOUToutput() {
    return LogProxy { pLogsOutput; };
}

其他一些一般性评论:

  1. 如果你想使用模板,你需要将其设为编译时条件。您可以使用 std::enable_if<> 之类的东西来提供 LOUToutput() 的多个模板重载,这些模板在 编译 时间选择要登录的位置。

  2. 我猜这只是为了发布到 SO,但是您的代码在头文件中声明了多个全局变量。你需要解决这个问题。

  3. 您的代码中没有 const 声明。许多这些运算符看起来至少应该在其输出(字符串等)参数上声明为 const。

编辑:这是这个想法的一个工作(正确编译)示例:

#include <iostream>

struct PRXY {
    bool cond;

    const PRXY &operator<<(const std::string &t) const {
        if(cond) {
            std::cout << t;
        } else {
            std::cerr << t;
        }
        return *this;
    }
};

PRXY pr(bool cond) {
    return PRXY { cond };
}

void test() {
    pr(false) << "Hello";
}