【问题标题】:Why does my compiler show this error about my constexpr function?为什么我的编译器会显示有关我的 constexpr 函数的此错误?
【发布时间】:2019-08-30 04:07:55
【问题描述】:

晚上好,

我必须用 constexpr 函数实现一个类,该函数在头文件中返回一个类成员。该成员是 const 并在我的构造函数中设置,因此稍后在程序中不会更改。

头文件实现:

//Creates a PreAllocString object
#define CREATE (varName,size) {\
    char string##varName##[size] {'\0'};\
    PreAllocString varName (string##varName##, size);\
}

class PreAllocString 
{
private:
    char* string;
    const std::size_t size;
    std::size_t length = 0;
    operator const char *() const;
    operator const void *() const;
    const char & operator [] (const int idx);

public:
    //Constructor
    PreAllocString (char* string, const std::size_t size);
.
.
.

CPP 文件实现:

#include "PreAllocString.h"

//Constructor
PreAllocString::PreAllocString (char* string, const std::size_t size) : string(string), size(size) {
    if (string != nullptr) {
        this->Empty();
    }
}
.
.
.

我的编译器总是显示:

In file included from src/PreAllocString.cpp:2:0:
include/PreAllocString.h:30:27: error: enclosing class of constexpr non-static member function ‘std::size_t PreAllocString::SizeOf()’ is not a literal type
     constexpr std::size_t SizeOf () {
                           ^
include/PreAllocString.h:11:7: note: ‘PreAllocString’ is not literal because:
 class PreAllocString 
       ^
include/PreAllocString.h:11:7: note:   ‘PreAllocString’ is not an aggregate, does not have a trivial default constructor, and has no constexpr constructor that is not a copy or move constructor

我做错了什么?

【问题讨论】:

  • 了解Literal Types。或者只是阅读您粘贴的错误消息。
  • 这是什么,C?在 C++ 中,如果可以的话,您希望远离使用宏定义来创建任何东西,更不用说使用宏连接了。试试它们在编译时构建的模板,应该能满足你的要求。
  • @Deduplicator 我已经阅读了 cppreference page about literals/constexpr 并试图了解什么是文字类型,我也尝试使用 int 类型而不是 size_t 因为这是文字类型(如果我做对了吗?),但它没有帮助。
  • 封闭类必须是文字类型。错误消息的含义非常明确。
  • @Tzalumen 我的教授希望我们使用“CREATE”Makro,它是一个嵌入式系统讲座。我对模板一无所知,我们必须将代码分发到周三。他说没有模板也可以解决问题。是否有解决该问题的方法或没有其他方法?

标签: c++ constructor constexpr


【解决方案1】:

这里是 C 人...我真的无法帮助您编写惯用的 C++,但我可以尝试解释为什么我能发现的一些事情是错误的。


#define CREATE (varName,size) {\  
 ... 
}

这可能不符合您的预期。我假设您正在尝试定义一个类似函数的宏,该宏扩展为声明一个数组和一个 PreAllocString 实例,所以像 CREATE(somename,somesize) 一样调用它会声明对象?
如果是这样……

  • 宏名称和它的参数列表之间不能有空格。如果有空格,则后面的任何内容都是扩展的一部分。例如:
    #define WORKS(varName) int varName
    #define DOESNT (varName) int varName
    WORKS(i); >> int i;
    DOESNT(i); >> (varName) int varName(i);

  • 宏主体周围的大括号不是宏定义的语法,将它们放在那里意味着它们出现在扩展中。即:
    CREATE(aName,6) ...
    >> { char stringaName[6] {'\0'}; //technically no line break PreAllocString aName (stringaName, 6); }

  • 除非您显示的代码不完整,或者有一些关于类构造函数的内容我根本不理解......您的构造函数的实现不应该调用这个东西吗?


#define CREATE (varName,size) {\
    char string##varName##[size] {'\0'};\
    PreAllocString varName (string##varName##, size);\
}

...varName ## [ size]...
...varName ## @ 987654336@ 大小...


这似乎没有表现出错误(目前......),但这不是令牌粘贴运算符的合法使用,您在这里得到的是未定义的行为。
https://en.cppreference.com/w/cpp/preprocessor/replace 令牌粘贴尝试将两个相邻的预处理器令牌组合成一个新的...并且[/, ('punctuators') 不能成为标识符令牌的一部分。 (除了意图之外,这是 varName 的唯一有效扩展,因为 other 标记粘贴指令:p) 这个案子的结果似乎是……什么都没有。您可以删除这些指令;连接失败后,未更改的单独令牌只是被单独摄取,就好像什么都没发生一样。不过,这种结果本质上是运气不佳。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多