blob: 65f7ddb8cf00b42b8623b6fd9e6be0b3836ad10a [file] [log] [blame]
/* { dg-do compile } */
/* { dg-options "-std=c++14 -O -fdump-tree-dse1-details" } */
using uint = unsigned int;
template<typename C, uint S>
struct FixBuf
{
C buf[S] = {};
};
template<typename C>
struct OutBuf
{
C* cur;
C* end;
C* beg;
template<uint S>
constexpr
OutBuf(FixBuf<C, S>& b) : cur{b.buf}, end{b.buf + S}, beg{b.buf} { }
OutBuf(C* b, C* e) : cur{b}, end{e} { }
OutBuf(C* b, uint s) : cur{b}, end{b + s} { }
constexpr
OutBuf& operator<<(C v)
{
if (cur < end) {
*cur = v;
}
++cur;
return *this;
}
constexpr
OutBuf& operator<<(uint v)
{
uint q = v / 10U;
uint r = v % 10U;
if (q) {
*this << q;
}
*this << static_cast<C>(r + '0');
return *this;
}
};
template<bool BOS>
struct BufOrSize
{
template<typename C, uint S>
static constexpr auto Select(FixBuf<C, S>& fb, OutBuf<C>&)
{
return fb;
}
};
template<>
struct BufOrSize<true>
{
template<typename C, uint S>
static constexpr auto Select(FixBuf<C, S>&, OutBuf<C>& ob)
{
return ob.cur - ob.beg;
}
};
// if BOS=1, it will return the size of the generated data, else the data itself
template<uint N, uint S, bool BOS = 0>
constexpr
auto fixbuf()
{
FixBuf<char, S> fb;
OutBuf<char> ob{fb};
for (uint i = 0; i <= N; ++i) {
ob << i << static_cast<char>(i == N ? 0 : ' ');
}
return BufOrSize<BOS>::Select(fb, ob);
}
auto foo()
{
constexpr auto x = fixbuf<13, 200>();
return x;
}
auto foo_sized()
{
constexpr auto s = fixbuf<13, 0, 1>();
constexpr auto x = fixbuf<13, s>();
return x;
}
int main()
{
}
/* { dg-final { scan-tree-dump-times "MEM <char\\\[\[0-9\]+]> \\\[\\(struct FixBuf \\*\\)&<retval> \\+ \[0-9\]+B\\\] = {}" 1 "dse1" } } */