2016-04-10 1 views
2

Простите меня, если это неосведомленный вопрос, но я все еще обнимаю голову, когда и как использовать спецификатор constexpr. (компиляция с msvc 14). Я работаю над простым базовым классом, который позволяет обернуть произвольный объект в «объект constexpr». Это выглядит следующим образом:Использование спецификатора Constexpr в функции производного класса

template<typename T> 
class basic_const { 
public: 

    explicit constexpr basic_const(const T& value) : data_(value) { } 

    template <typename...Args> 
    constexpr basic_const(Args&&...args) : data_(T(std::forward<Args>(args)...)) { } 

    virtual ~basic_const() = default; 

    constexpr const T& data() const noexcept { return data_; } 

private: 
    T data_; 
}; 

Все работает, как и ожидалось, я могу успешно создать объект любого типа, который может (очевидно) квалифицируются как constexpr.

В этом случае:
При попытке наследовать от этого класса я не могу реализовать дополнительные функции-члены constexpr, но я могу использовать ctors. Следующий код для класса constexpr строки я реализую:

class str_const : public basic_const<const char*> 
{ 
public: 

    template <std::size_t N> 
    constexpr str_const(const char(&str)[N]) : 
     basic_const(str), sz_(N) {} 
    ... 
    constexpr std::size_t size() const noexcept{ return sz_; } // error here 
    ... 
public: 
    std::size_t sz_; 
}; 

Могу ли я создать constexpr функции члена в производном классе?

ответ

2

Проблема, похоже, не в том, что вы написали в your answer. Проблема заключается в том, что охватывающий класс не является literal type, из-за существования виртуального деструктора (то есть, non-trivial destructor). НКУ выплевывает (подчеркнуть мой):

error: enclosing class of constexpr non-static member function 'std::size_t str_const::size() const' is not a literal type

Live example with the error

Удалите virtual классификатор из деструктора, и он будет работать.

Live example working

Там нет необходимости в дополнительных const с для переменных-членов.

EDIT

лязг однако compiles your code just fine ... Интересно, если это ошибка. Теперь поняли, что это действительно ошибка clang, как virtual destructor is non-trivial, поэтому clang не должен компилировать ваш код как есть.

+0

спасибо, прояснилось немного! –

+0

@NowhereMan Добро пожаловать, хороший вопрос. Я все еще пытаюсь придумать минимальный пример для заполнения ошибки clang. – vsoftco

+0

Ограничение, которое функции constexpr-члена могут быть объявлены только для литеральных типов, было ограничением C++ 11, задним числом снятым с C++ 11 с CWG1684 и полностью удаленным из C++ 14. GCC здесь не прав, Клэнг прав, и, таким образом, этот ответ неверен. ; -D (EDIT: конкретная формулировка, которая была изменена, была в [dcl.constexpr]/8; предложение «* Класс, членом которого является эта функция, является литеральный тип. *» Был удален.) – ildjarn

0

кажется, что я пытаюсь слишком выполнить это вполне приемлемо, переменная члена в производном классе не был объявлен const, изменяя переменные базового и производного класса к const исправили проблему.