为了防止编译器将例如 a 应用于std::vector<T>类似的语句std::cout << u,我想做这样的事情:
if constexpr (std::has_output_operator<U>) {\n std::cout << u;\n}\nRun Code Online (Sandbox Code Playgroud)\n有什么方法可以实现这一目标吗?
\n编辑(澄清)\n我正在研究类似 printf 的函数,它也可以打印 POD 的字符串和向量以及字符串(及其向量)。
\n我想将此功能扩展到任何具有输出运算符的类型。
\n非向量类型的实际格式化是由函数完成的simpleFormat():
// simpleFormat\n// special case for single string\n//\nstd::string simpleFormat(const std::string sFormat, const std::string t) {\n size_t required = snprintf(NULL, 0, sFormat.c_str(), t.c_str());\n char sTemp[required+1];\n sprintf(sTemp, sFormat.c_str(), t.c_str());\n return std::string(sTemp);\n} \n\n// simpleFormat\n// catch for vectors (should not be sent to simpleFormat)\ntemplate<typename T>\nstd::string simpleFormat(const std::string sFormat, const std::vector<T> t) {\n return "";\n}\n\n// simpleFormat\n// formatting PODs and Objects with output operator a char using \ntemplate<typename T>\nstd::string simpleFormat(const std::string sFormat, const T t) {\n std::string sRes = "";\n\n if (sFormat.size() > 0) {\n if (sFormat != "%O") {\n size_t required = snprintf(NULL, 0, sFormat.c_str(), t);\n char sTemp[required+1];\n sprintf(sTemp, sFormat.c_str(), t);\n sRes = std::string(sTemp);\n } else {\n std::stringstream ss("");\n ss << t;\n sRes += ss.str(); \n }\n } \n\n return sRes;\n}\nRun Code Online (Sandbox Code Playgroud)\n当我为某些应用程序编译此文件时,出现错误
\nIn file included from AgentCounter.cpp:6: \n../utils/stdstrutilsT.h: In instantiation of \xe2\x80\x98std::string simpleFormat(std::string, T) [with T = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; std::string = std::__cxx11::basic_string<char>]\xe2\x80\x99: \n../utils/stdstrutilsT.h:195:33: required from \xe2\x80\x98std::string recursiveFormat(stringvec&, stringvec&, uint, T, Args ...) [with T = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; Args = {long long unsigned int}; std::string = std::__cxx11::basic_string<char>; stringvec = std::vector<std::__cxx11::basic_string<char> >; uint = unsigned int]\xe2\x80\x99 \n../utils/stdstrutilsT.h:281:31: required from \xe2\x80\x98std::string stdsprintf(std::string, Args ...) [with Args = {__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, long long unsigned int}; std::string = std::__cxx11::basic_string<char>]\xe2\x80\x99 \n../utils/stdstrutilsT.h:291:34: required from \xe2\x80\x98void stdprintf(std::string, Args ...) [with Args = {__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, long long unsigned int}; std::string = std::__cxx11::basic_string<char>]\xe2\x80\x99 \nAgentCounter.cpp:326:22: required from here \n../utils/stdstrutilsT.h:165:28: error: no match for \xe2\x80\x98operator<<\xe2\x80\x99 (operand types are \xe2\x80\x98std::stringstream\xe2\x80\x99 {aka \xe2\x80\x98std::__cxx11::basic_stringstream<char>\xe2\x80\x99} and \xe2\x80\x98const __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >\xe2\x80\x99) \n 165 | ss << t; \n | ~~~^~~~ \nRun Code Online (Sandbox Code Playgroud)\n即使我有simpleFormat()向量的变体,编译器仍然希望将其适合std::vectorPOD 变体。
这就是为什么我希望有一个constexpr可以让我找出传递的类型是否有输出运算符的原因。
当然,如果还有其他可能性阻止编译器将向量应用于我的非向量函数,我想了解它们。
\n这可以使用 C++20要求表达式直接完成,它检查其操作数是否有效:
if constexpr (requires { std::cout << u; })
Run Code Online (Sandbox Code Playgroud)
您还可以使用需求表达式定义命名概念,然后在每次需要时使用它来代替需求表达式。