C ++ 11可变参数模板和std :: endl [英] c++11 variadic templates and std::endl

查看:148
本文介绍了C ++ 11可变参数模板和std :: endl的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用C ++ 11可变参数模板进行记录器,但不适用于 std :: endl ,因为 std: :endl 是模板函数,编译器不知道选择 std :: endl 的哪种专业。有什么方法可以强制我始终选择 std :: endl< char,std :: char_traits< char>> ?如果可能的话,我想直接使用std :: endl。

I tried to do logger using C++11 variadic templates, but it doesn't work for std::endl, because std::endl is template function and the compilator doesn't know what specialization of std::endl to select. Is there any way how i can force to always select std::endl<char, std::char_traits<char>>? If possible, i want to use directly std::endl.

编辑:看来C ++ 11当前无法使用最好的方法是使用 #define vsoftco 回答。

it looks like it is not currently possible with C++11 and and best way is to use #define or what vsoftco answered.

#include <iostream>
#include <string>

class Logger {

public:

    template<typename T>
    void log(T val);

    template <typename T, typename ...Args>
    void log(T val, Args... args);

};

// explicit specialization not working 
template<>
void Logger::log(std::basic_ostream<char, std::char_traits<char>> (*modifier) (std::basic_ostream<char, std::char_traits<char>>)) {

    std::cout << modifier;

}

template<typename T>
void Logger::log(T val) {

    std::cout << val;

}

template<typename T, typename ...Args>
void Logger::log(T val, Args... args) {

    log(val);
    log(args...);

}

int main(int argc, char* argv[])
{   
    Logger log;

    log.log("Nazdar ", "bazar ", "cau", std::endl, "kik"); // ERROR: cannot determine which instance of function template "std::endl" is intended
    log.log("Nazdar ", "bazar ", "cau", std::endl<char, std::char_traits<char>>, "kik");

    std::cin.get();

    return 0;
}


推荐答案

我想到了这个,基本上是通过使用默认模板参数的自定义包装 my_endl 重新定义 std :: endl 的。不是最优雅的,但可以做到。当然,对于更多这样的操纵器,应该编写一个专门的包装器,但是我想,即使这样也可以通过更聪明的实现来实现。

I came up with this, basically re-defining std::endl via a custom wrapper my_endl taking default template parameters. Not the most elegant, but it does the job. Of course, for more such manipulators, one should write a specialized wrapper, but I guess even this can somehow be possible by a more clever implementation.

#include <iostream>
#include <string>
#include <type_traits>

class Logger {

public:

    template<typename T>
    void log(T val);

    template <typename T, typename ...Args>
    void log(T val, Args... args);
};

template<typename T>
void Logger::log(T val) {
    std::cout << val;
}

template<typename T, typename ...Args>
void Logger::log(T val, Args... args) {

    log(val);
    log(args...);

}

template< class CharT = char, class Traits = std::char_traits<CharT> >
inline std::basic_ostream<CharT, Traits>& my_endl( std::basic_ostream<CharT, Traits>& os )
{
    return std::endl(os);
} 

// or, use the excellent (and better) suggestion by 0x499..., 
// auto manip = std::endl<char, std::char_traits<char>>; 
// log.log(..., manip)


int main(int argc, char* argv[])
{
    Logger log;

    // log.log("Nazdar ", "bazar ", "cau", std::endl, "kik"); // ERROR: cannot determine which instance of function template "std::endl" is intended
    log.log("Nazdar ", "bazar ", "cau", my_endl<>, "kik");

    std::cin.get();

    return 0;
}

这篇关于C ++ 11可变参数模板和std :: endl的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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