是否有一个 constexpr 可以让我确定特定类型是否有输出运算符 (<<)?

use*_*670 3 c++ if-constexpr

为了防止编译器将例如 a 应用于std::vector<T>类似的语句std::cout << u,我想做这样的事情:

\n
if constexpr (std::has_output_operator<U>) {\n    std::cout << u;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

有什么方法可以实现这一目标吗?

\n

编辑(澄清)\n我正在研究类似 printf 的函数,它也可以打印 POD 的字符串和向量以及字符串(及其向量)。

\n

我想将此功能扩展到任何具有输出运算符的类型。

\n

非向量类型的实际格式化是由函数完成的simpleFormat():

\n
// 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}\n
Run Code Online (Sandbox Code Playgroud)\n

当我为某些应用程序编译此文件时,出现错误

\n
In 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     |                         ~~~^~~~ \n
Run Code Online (Sandbox Code Playgroud)\n

即使我有simpleFormat()向量的变体,编译器仍然希望将其适合std::vectorPOD 变体。

\n

这就是为什么我希望有一个constexpr可以让我找出传递的类型是否有输出运算符的原因。

\n

当然,如果还有其他可能性阻止编译器将向量应用于我的非向量函数,我想了解它们。

\n

Bri*_*ian 6

这可以使用 C++20要求表达式直接完成,它检查其操作数是否有效:

if constexpr (requires { std::cout << u; })
Run Code Online (Sandbox Code Playgroud)

您还可以使用需求表达式定义命名概念,然后在每次需要时使用它来代替需求表达式。