C++ 当当前字符串的长度与前一个字符串的长度相同时,为什么我的字符串联接程序发出前一个字符串而不是当前字符串
所以,我有以下花式细绳木工:C++ 当当前字符串的长度与前一个字符串的长度相同时,为什么我的字符串联接程序发出前一个字符串而不是当前字符串,c++,templates,C++,Templates,所以,我有以下花式细绳木工: #include <iostream> #include <sstream> class Internal final { ~Internal() = delete; static std::stringstream stream; static const std::ios_base::fmtflags defflags; template <typename T, typename ...P>
#include <iostream>
#include <sstream>
class Internal final
{
~Internal() = delete;
static std::stringstream stream;
static const std::ios_base::fmtflags defflags;
template <typename T, typename ...P> struct Append
{
static void func(const void *const *p)
{
stream << *(T *)*p;
Append<P...>::func(p + 1);
}
};
template <typename T> struct Append<T>
{
static void func(const void *const *p)
{
stream << *(T *)*p;
}
};
template <typename ...P> friend const char *Jo(const P &... p);
};
std::stringstream Internal::stream;
const std::ios_base::fmtflags Internal::defflags = stream.flags();
template <typename ...P> const char *Jo(const P &... p) // 'Join', returned pointer is valid until next call
{
Internal::stream.clear();
Internal::stream.flags(Internal::defflags);
Internal::stream.str("");
const void *const arr[sizeof...(P)] {&p...};
Internal::Append<P...>::func(arr);
static std::string ret = Internal::stream.str();
return ret.c_str();
}
我希望它打印1234
,但它打印1212
当我在一行中多次使用我的函数时,当得到的每个字符串都具有相同的长度时,总是会发生同样的情况。在这些情况下,它总是打印序列中的第一个字符串
有人知道为什么会这样吗?
另外,这个问题与std::cout
优化无关,我也在没有std::cout
的情况下测试了它
static std::string ret = Internal::stream.str();
。。。只执行一次,因为它是静态
变量的初始值设定项。只需删除它并从Internal::stream.str()
返回一个std::string
这里有一个版本的Jo
,如果你想获得灵感的话。我保留了静态的stringstream
,但将其用于Jo
的所有实例化,但我不确定共享它是否有意义(线程安全问题等)。我会把国旗交给你;)
namespace jou\u详细信息{
std::stringstream;
}
模板
std::string Jo(Args&&…Args){
Jo_detail::stream.str(“”);
//使用虚拟阵列的经典扩展器技巧
使用ex=int[];
(void)ex{0,(void(Jo_detail::stream)您可能应该删除void*
madness,这毕竟是模板的卖点之一。为什么不简单地使用operator@Quentin我使用它是因为我看到的唯一其他解决方案是向Append()传递一组引用
每次都是。我认为它可以让蹩脚的编译器稍微慢一点,但我不确定。@πάνταῥεῖ 你是说每次我需要压缩字符串时都要手动使用stringstream吗?因为使用此函数的代码更紧凑。@HolyBlackCat…显然可靠性更低;-)哎呀。看来我没注意到,因为每种arg类型的组合都有新的实例!在编辑之前,我以为我对模板功夫有所了解。:)顺便说一句,你的解决方案几乎奏效了:.clear()
清除错误状态,而不是内容。@HolyBlackCat诅咒那个糟糕的前标准接口!现在已经修复:pI个人发现直接使用那个技巧没有什么用处。模板void run(Fs&&…Fs){using ex=int[];(void)ex{0,(std::forward(Fs)),void(),0)};
助手,然后运行([&]{Jo_detail::stream@Yakk-ouch。这可能是我更喜欢宏的地方之一。
std::cout << Jo('1','2');
std::cout << Jo('3','4');
static std::string ret = Internal::stream.str();
namespace Jo_detail {
std::stringstream stream;
}
template <class... Args>
std::string Jo(Args &&... args) {
Jo_detail::stream.str("");
// Classic expander trick with dummy array
using ex = int[];
(void) ex { 0, (void(Jo_detail::stream << std::forward<Args>(args)), 0)... };
// str() returns a copy anyway
return Jo_detail::stream.str();
}