How to deduce the size of a compile time a const char string with C++ templates?

百般思念 提交于 2021-02-08 11:30:48

问题


I am trying to use clang++ to expand the template code from this post. Here is what I come up with.

constexpr unsigned int requires_inRange(unsigned int i, unsigned int len) {
    return i >= len ? throw i : i;
}

class StrWrap
{
    unsigned size_;
    char * const begin_;

public:
    template< unsigned N >
    constexpr StrWrap( const char(&arr)[N] ) : begin_(arr), size_(N - 1) {
        static_assert( N >= 1, "not a string literal");
    }

    constexpr char operator[]( unsigned i ) {
        return requires_inRange(i, size_), begin_[i];
    }

    constexpr operator const char *() {
        return begin_;
    }

    constexpr unsigned size() {
        return size_;
    }
};

constexpr unsigned count( StrWrap str, char c, unsigned i = 0, unsigned ans = 0 )
{
    return i == str.size() ? ans :
               str[i] == c ? count(str, c, i + 1, ans + 1) :
                             count(str, c, i + 1, ans);
}

int main(int argc, char const *argv[])
{
    static_assert( count("dude", 'd') == 2, "d != 2" );
    return 0;
}

However, the code from the blog post is not compiling:

/usr/bin/clang++ -Xclang -ast-print -fsyntax-only test_debugger2.cpp > main.exe

test_debugger2.cpp:12:48: error: cannot initialize a member subobject of type 'char *const' with an lvalue of type 'const char [5]'
    constexpr StrWrap( const char(&arr)[N] ) : begin_(arr), size_(N - 1) {
                                               ^      ~~~
test_debugger2.cpp:38:26: note: in instantiation of function template specialization 'StrWrap::StrWrap<5>' requested here
    static_assert( count("dude", 'd') == 2, "d != 2" );
                         ^
test_debugger2.cpp:38:20: error: static_assert expression is not an integral constant expression
    static_assert( count("dude", 'd') == 2, "d != 2" );
                   ^~~~~~~~~~~~~~~~~~~~~~~
2 errors generated.

I could find this related question Cannot initialize a member subobject of type 'const signed char *' with an lvalue of type 'const char [X]', but I did not get how I could fix it.

By using the flags -Xclang -ast-print -fsyntax-only I am only asking clang to expand the templates and print their expansion to stdout: Compile-time 'String' Manipulation with Variadic Templates

I am trying to learn to do string computations, i.e., string splitting, string concatenation, find, replace, cut, etc, at compile time with C++ Templates which are said to be Turing Complete: C++ templates Turing-complete?, then, I am taking examples as that blog post and expanding them with clang to see how they work and how I could use them to solve any compile time (possible) computations with templates.

This is my compiler version:

clang version 8.0.1 (tags/RELEASE_801/final)
Target: x86_64-unknown-windows-cygnus
Thread model: posix
InstalledDir: /usr/bin

How could I fix the template expansion from that blog post?


回答1:


This

char * const begin_;

is a const pointer to char (the pointer is const, not the thing it points to). This

const char(&arr)[N]

is a reference to an array of N elements of type const char. The element of the array are const. You cannot have a pointer to non-const point into an array of const elements (at least not without brute force). You need to either make your pointer a const char* or make your array an array of non-const elements…

I guess you mean to write

const char* begin_;

Note: starting with C++17, you can just use std::string_view…



来源:https://stackoverflow.com/questions/59418505/how-to-deduce-the-size-of-a-compile-time-a-const-char-string-with-c-templates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!