/* FILE: c.cc */
#include<cstdio>
#include<type_traits>
constexpr size_t strlenConstexprByPointerTail(char const *p, size_t acc)
{
return *p ? strlenConstexprByPointerTail(p + 1, acc + 1) : 0;
}
constexpr size_t strlenConstexprByPointer(char const *p)
{
return p ? strlenConstexprByPointerTail(p, 0) : 0;
}
template <size_t len>
constexpr size_t strlenConstexprByArrayLoop(char const (&p)[len], size_t i)
{
return p[i] ? strlenConstexprByArrayLoop(p, i + 1) : i;
}
template <size_t len>
constexpr size_t strlenConstexprByArray(char const (&p)[len])
{
return strlenConstexprByArrayLoop(p, 0);
}
template <typename T>
struct strlenConstexprHelper { };
template <>
struct strlenConstexprHelper<char const *>
{
typedef size_t type;
static constexpr size_t strlenConstexpr(char const *p)
{
return strlenConstexprByPointer(p);
}
};
template <>
struct strlenConstexprHelper<char const *&> : strlenConstexprHelper<char const *> { };
template <>
struct strlenConstexprHelper<char *> : strlenConstexprHelper<char const *> { };
template <>
struct strlenConstexprHelper<char *&> : strlenConstexprHelper<char const *> { };
template <size_t len>
struct strlenConstexprHelper<char const (&)[len]>
{
typedef size_t type;
static constexpr size_t strlenConstexpr(char const (&p)[len])
{
return strlenConstexprByArray(p);
}
};
template <size_t len>
struct strlenConstexprHelper<char (&)[len]> : strlenConstexprHelper<char const (&)[len]>
{
};
template <>
struct strlenConstexprHelper<nullptr_t>
{
typedef size_t type;
static constexpr size_t strlenConstexpr(nullptr_t)
{
return 0;
}
};
template <typename T>
constexpr typename strlenConstexprHelper<T>::type strlenConstexprUnified(T &&value)
{
return strlenConstexprHelper<T>::strlenConstexpr(std::forward<T>(value));
}
int main()
{
// good
char array1[strlenConstexprByPointer(nullptr) + 10] = { };
// bad
char array2[strlenConstexprByPointer("Hello, world!")] = { };
// good
char array3[strlenConstexprByArray("Hello, world!")] = { };
// bad
char array4[strlenConstexprByArray(nullptr) + 10] = { };
// good
char array5[strlenConstexprUnified("Hello, world!")] = { };
// good
char array6[strlenConstexprUnified(nullptr) + 10] = { };
// good
strlenConstexprUnified(array5);
// good
auto *p = array6;
strlenConstexprUnified(p);
return 0;
}
/* cl c.cc
Microsoft (R) C/C++ Optimizing Compiler Version 19.15.26726 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
c.cc
c.cc(86): error C2466: cannot allocate an array of constant size 0
c.cc(86): error C2133: 'array2': unknown size
c.cc(90): error C2672: 'strlenConstexprByArray': no matching overloaded function found
c.cc(90): error C2784: 'size_t strlenConstexprByArray(const char (&)[len])': could not deduce template argument for 'const char (&)[len]' from 'nullptr'
c.cc(23): note: see declaration of 'strlenConstexprByArray'
c.cc(90): error C2133: 'array4': unknown size
*/