Почему мой компилятор показывает эту ошибку о моей функции constexpr? - PullRequest
0 голосов
/ 09 апреля 2019

Добрый вечер,

Мне нужно реализовать класс с функцией 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

Что я делаю не так?

1 Ответ

0 голосов
/ 09 апреля 2019

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 ## [ размер]. ..
... varName ## , размер ...


Кажется, что это не проявляется ошибка (на данный момент ...), но это не законное использование оператора вставки токена, и то, что вы получаете здесь, является неопределенным поведением.
https://en.cppreference.com/w/cpp/preprocessor/replace
Вставка токенов пытается объединить два смежных токена препроцессора в один новый ... и [ / , ('punctuators') не может быть частью идентификатора токенов. (которые, кроме намерения, являются единственными действительными расширениями для varName из-за директивы вставки токенов other : p) Результат, который имеет место для этого дела, кажется ... ничем. Вы можете просто удалить эти директивы; после сбоя конкатенации неизмененные отдельные токены просто попадают отдельно, как будто ничего не произошло. Этот результат, по сути, глупая удача.

...