c++ - 如何通过CTOR从constexpr中的STRING LITERAL初始化char数组成员

标签 c++ constexpr string-literals

所以这工作:

        template<size_t N>
        struct LTxt
        {
            char txt[N];
        };
        void Test1()
        {
            //LTxt<10> fromliteral = "test1"; does not work, but ok
            LTxt<10> fromlitera2 = { "test2" };
            constexpr LTxt<10> fromliteral3 = { "test3" };
        }
但是,当您为该结构编写构造函数时,就会失去该自动“特权”。
我可以写什么构造函数实现来保留该功能。
我尝试了很多事情:(注释的代码不起作用)
template<size_t N>
        struct LTxt2
        {
            char txt[N];

            //LTxt2() = default; // doesnt change anything

            template<size_t N>
            constexpr LTxt2(const char(&sz)[N])
                //: txt{ sz } // Error  C2075 array initialization requires a brace - enclosed initializer list
            {
                for (int c = 0; c < N; ++c) txt[c] = sz[c];
            }
        };
        void Test2()
        {
            LTxt2<10> fromliteral = "test1";
            //constexpr LTxt2<10> fromliteral2 = "test2";
            LTxt2<10> fromliteral3 = { "test3" };
            //constexpr LTxt2<10> fromliteral4 = { "test4" };
            LTxt2<10> fromliteral5("test5");
            //constexpr LTxt2<10> fromliteral6("test6");
            LTxt2<10> fromliteral7({ "test7" });
            //constexpr LTxt2<10> fromliteral8({ "test8" });
        }

        template<size_t N>
        struct LTxt3
        {
            char txt[N];

            constexpr LTxt3(std::initializer_list<char> list)
                //:txt(list) {}
                //:txt{ list }// {}
            {
                int c = 0;
                for (auto p = list.begin(); p != list.end(); ++p, ++c)
                    txt[c] = *p;
            }
        };
        void Test3()
        {
            //LTxt3<10> fromliteral = "test1";
            //constexpr LTxt3<10> fromliteral2 = "test2";
            //LTxt3<10> fromliteral3 = { "test3" }; //why in the name of fuck that doesnt work
            //constexpr LTxt3<10> fromliteral4 = { "test4" };
            //LTxt3<10> fromliteral5("test5");
            //constexpr LTxt3<10> fromliteral6("test6");
            //LTxt3<10> fromliteral7({ "test7" });
            //constexpr LTxt3<10> fromliteral8({ "test8" });
            LTxt3<10> fromliteral9 = { 't','e','s','t','9' };
            //constexpr LTxt3<10> fromliteral10 = { 't','e','s','t','1', '0' };
        }

        template<size_t N>
        struct LTxt4
        {
            char txt[N];

            template<typename ... Params>
            constexpr LTxt4(Params ... sz)
                : txt{ sz... }
            {}
        };


        void Test4()
        {
            //LTxt4<10> fromliteral = "test1";
            //LTxt4<10> fromliteral = { "test1" };
            //LTxt4<10> fromliteral { "test1" };
            //LTxt4<10> fromliteral("test1");
            LTxt4<10> fromliteral = { 't','e','s','t','1' };
            constexpr LTxt4<10> fromliteral2 = { 't','e','s','t','2' };
        }

最佳答案

我想出了这个:

#include <iostream>
#include <stdexcept>

template<size_t N>
struct LTxt
{
    char txt[N] {};
};


template <class Char, Char... Cs>
constexpr auto operator""_txt()
{
    LTxt<sizeof...(Cs)> text;
  
    size_t index = 0;
    auto addChar = [&](char c)
    {
        text.txt[index] = c;
        index++;
    };
    
    ((addChar(Cs)), ...);

    return text;
}

int main() {
    constexpr auto txt = "test"_txt; 
    
    for (int i = 0 ; i < 4 ; i++)
    {
        std::cout << txt.txt[i] << std::endl;
    }

}
注意:带有字符参数包的字符串文字运算符模板是GNU扩展,不适用于-pedantic-errors。 clang和gcc都支持它。

我要支持以下语法:
std::cout << txt.txt << std::endl;
您需要添加一个'\0':
template <class Char, Char... Cs>
constexpr auto operator""_txt()
{
    LTxt<sizeof...(Cs)+1> text;
    size_t index = 0;
    auto addChar = [&](char c)
    {
        text.txt[index] = c;
        index++;
    };
    ((addChar(Cs)), ...);
    text.txt[index] = '\0';
    return text;
}

语法:((addChar(Cs)), ...);fold expression
在c++ 17之前,可以使用此技巧模拟它:
auto initializerList = {
       (
           addChar(Cs)   // real code
           , 0           // the expression is evaluated at 0 each time
       )...              // expand the parameter pack, 
       , 0               // if we do: ""_txt; 
                         // we need at least one element for the auto deduction
};
(void) initializerList; // silence warning
之所以有效,是因为parameter pack扩展:

expands to comma-separated list of zero or more patterns. Pattern must include at least one parameter pack.


因此,它将为addChar(Cs),0中的每个char重复整个Cs

关于c++ - 如何通过CTOR从constexpr中的STRING LITERAL初始化char数组成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64072879/

相关文章:

c++ - 最小 float (最接近零)

c++ - 如何将 const 数组存储在可执行文件中?

c++ - 为什么我在插入 map 时会出现段错误

c++ - 为什么我必须将 const 与 constexpr 一起用于静态类函数?

c++ - constexpr 类的设计 : merging constexpr and non-constexpr versions?

c# - 如何在逐字字符串中包含逐字字符串?

编译器不允许我编辑传递的字符串

java - 文字字符串方法与对象方法

c++ - 命令行参数 c++

c++ - 如何将灰度/二进制 Mat 转换为 QImage?