[ create a new paste ] login | about

Link: http://codepad.org/X2D62VwD    [ raw code | fork ]

geelaw - Plain Text, pasted on Sep 23:
/* 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

*/



Create a new paste based on this one


Comments: