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

Is there a constexpr which lets me determine if there is an output operator (<<) for a particular type?

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

if constexpr (std::has_output_operator<U>) {
    std::cout << u;
}

有什么方法可以实现吗?

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

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

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

// simpleFormat
//  special case for single string
//
std::string simpleFormat(const std::string sFormat, const std::string t) {
    size_t required = snprintf(NULL, 0, sFormat.c_str(), t.c_str());
    char sTemp[required+1];
    sprintf(sTemp, sFormat.c_str(), t.c_str());
    return std::string(sTemp);
} 

// simpleFormat
//  catch for vectors (should not be sent to simpleFormat)
template<typename T>
std::string simpleFormat(const std::string sFormat, const std::vector<T> t) {
    return "";
}

// simpleFormat
//  formatting PODs and Objects with output operator a char using     
template<typename T>
std::string simpleFormat(const std::string sFormat, const T t) {
    std::string sRes = "";

    if (sFormat.size() > 0) {
        if (sFormat != "%O") {
            size_t required = snprintf(NULL, 0, sFormat.c_str(), t);
            char sTemp[required+1];
            sprintf(sTemp, sFormat.c_str(), t);
            sRes = std::string(sTemp);
        } else {
            std::stringstream ss("");
            ss << t;
            sRes += ss.str();    
        }
    } 

   return sRes;
}

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

In file included from AgentCounter.cpp:6: 
../utils/stdstrutilsT.h: In instantiation of ‘std::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>]’: 
../utils/stdstrutilsT.h:195:33:   required from ‘std::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]’ 
../utils/stdstrutilsT.h:281:31:   required from ‘std::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>]’ 
../utils/stdstrutilsT.h:291:34:   required from ‘void 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>]’ 
AgentCounter.cpp:326:22:   required from here 
../utils/stdstrutilsT.h:165:28: error: no match for ‘operator<<’ (operand types are ‘std::stringstream’ {aka ‘std::__cxx11::basic_stringstream<char>’} and ‘const __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >’) 
 165 |                         ss << t; 
     |                         ~~~^~~~ 

即使我有一个 simpleFormat() 向量变体,编译器仍然希望将 std::vector 放入 POD 变体中。

这就是为什么我希望 constexpr 让我查明传递的类型是否有输出运算符。

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

这可以使用 C++20 requires-expression 直接完成,它会检查其操作数是否有效:

if constexpr (requires { std::cout << u; })

您还可以使用 requires-expression 定义命名的 concept,然后用它代替 requires-expression每次你需要的时候。