编译器无法推断出要返回的模板类型

时间:2017-03-05 20:35:10

标签: c++ operator-overloading output fstream

相关代码是:

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类,因此取消引用其指针会崩溃,在这种情况下我宁愿输出到文件。 我知道编译器在编译时无法告诉LogsOutput类是否会被实例化,因此不能推断出模板的类型,但我没有看到任何其他方法可以使它工作。 所以我的问题是我的函数如何根据运行时条件返回不同的类型?

1 个答案:

答案 0 :(得分:2)

对此的复杂解决方案是使用继承。如果你要从std :: ostream继承,你可以返回一个公共基类(如果你感兴趣的话,这是一个讨论:How to inherit from std::ostream?

更简单的解决方案是,返回一个代理类,根据需要重定向输出。

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&lt;&gt;这样的东西。提供LOUToutput()的多个模板重载,在编译时选择登录的位置。

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

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

  4. 编辑:这是一个有效的(正确编译)样本:

    #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";
    }