C ++ 11 variation templates and std :: endl

I tried to make a registrar using C ++ 11 variadic templates, but it does not work for std::endl , because std::endl is a template function, and the compiler does not know which specialization std::endl should choose. Is there a way that I can make it always choose std::endl<char, std::char_traits<char>> ? If possible, I want to use std :: endl directly.

EDIT: It looks like this is currently not possible in C ++ 11, and it is best 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; } 
+6
source share
2 answers

I came up with this, basically overriding std::endl using the custom my_endl shell, accepting the default template options. Not the most elegant, but he does his job. Of course, for more of these manipulators you need to write a special shell, but I think that even this can be somehow possible with the help of a smarter 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; } 
+3
source

A simpler option to achieve the same goal:

 // global or class member enum MyEndl { my_endl }; // class member function void log(MyEndl x) { std::cout << std::endl; } 

using:

 log.log("Nazdar ", "bazar ", "cau", my_endl, "kik"); 
+5
source

Source: https://habr.com/ru/post/984369/


All Articles