是否有一个 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每次你需要的时候。
为了防止编译器应用例如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每次你需要的时候。