Desain kelas constexpr: menggabungkan versi constexpr dan non-constexpr?

Pertimbangkan kelas yang baru saja membungkus nilai saat runtime :

template <typename Type>
class NonConstValue 
{
    public:
        NonConstValue(const Type& val) : _value(val) {;}
        Type get() const {return _value;}
        void set(const Type& val) const {_value = val;}
    protected:
        Type _value;
};

dan versi constexprnya:

template <typename Type>
class ConstValue 
{
    public:
        constexpr ConstValue(const Type& val) : _value(val) {;}
        constexpr Type get() const {return _value;}
    protected:
        const Type _value;
};

Pertanyaan 1 : Dapatkah Anda memastikan bahwa versi constexpr dirancang dengan cara yang benar?

Pertanyaan 2 : Bagaimana Anda menggabungkan kedua kelas menjadi satu yang disebut Value yang dapat dibuat constexpr atau dibuat pada waktu proses dan yang nilainya dapat get() pada waktu proses atau waktu kompilasi?

EDIT: Pertanyaan 3: Jika get() didefinisikan dalam file .cpp, dan jika saya ingin get() disisipkan jika bukan constexpr, apa deklarasi fungsi yang benar? Apakah itu

constexpr inline Type get();

or

inline constexpr Type get()

atau sesuatu yang lain ?


person Vincent    schedule 18.01.2013    source sumber
comment
constexpr fungsi dapat dipanggil pada waktu kompilasi atau waktu proses.   -  person chris    schedule 18.01.2013
comment
Saya berpendapat bahwa fungsi anggota constexpr non-statis mempunyai kelemahan karena selalu menyiratkan kualifikasi fungsi const, yaitu constexpr foo bar(); adalah deklarasi yang sama dengan constexpr foo bar() const;. Tidak ada persyaratan seperti itu untuk non-anggota, yaitu constexpr foo bar(T&); atau constexpr foo bar(T&&); keduanya dapat menerima non-const T (dan dimungkinkan untuk memiliki ekspresi konstan yang melibatkan tipe kelas berkualifikasi non-const). Jadi berhati-hatilah terhadap hal itu.   -  person Luc Danton    schedule 18.01.2013


Jawaban (2)


Cukup tambahkan penentu constexpr ke masing-masing fungsi yang berpotensi menjadi ekspresi konstan.

template <typename Type>
class Value 
{
public:
    constexpr Value(Type const& val) : _value(val) {}
    constexpr Type const& get() const {return _value;}
    void set(Type const& val) {_value = val;}
protected:
    Type _value;
};

Anda tidak memerlukan versi const dan non-const, karena hal tersebut dapat dilakukan dengan membuat instance template Value dengan const atau < tipe em>non-const.

Anda tidak memerlukan versi constexpr dan non-constexpr, constexpr berarti ekspresi konstan potensial dan apakah ekspresi tersebut akhirnya menjadi ekspresi konstan atau tidak bergantung pada argumennya. Apakah ekspresi tersebut akan dievaluasi pada waktu kompilasi atau tidak bergantung pada konteks dan implementasinya.

person K-ballo    schedule 18.01.2013
comment
+1, itulah yang ingin saya katakan. Bahkan mutable diperbolehkan di dalam objek constexpr. - person Potatoswatter; 18.01.2013
comment
Benar-benar rewel, tapi constexpr adalah penentu, bukan deklarator. - person aschepler; 18.01.2013
comment
@aschepler: Terima kasih, saya tahu itu bukan pengubah tetapi saya melewatkan istilah yang benar. - person K-ballo; 18.01.2013
comment
@Vincent: Menambahkan inline tidak akan memengaruhi apakah fungsinya sebaris atau tidak. Jika berada di .cpp yang berbeda maka mungkin tidak akan terjadi, karena kompiler tidak dapat melihat definisinya dari luar .cpp tersebut - person K-ballo; 18.01.2013
comment
+1 untuk jawaban yang benar. Catatan: Tidak perlu mendeklarasikan get() sebagai constexpr dan const. Yang pertama menyiratkan yang kedua. - person jogojapan; 18.01.2013
comment
Saya pikir memiliki dua fungsi terpisah masih dapat berguna, karena fungsi constexpr tidak dapat memiliki lokal statis, antara lain - person ; 28.07.2015

Kelas constexpr Anda dirancang dengan benar, kecuali Anda salah mengetik nama konstruktornya (seharusnya ConstValue, bukan Value). Tapi saya yakin itu hanya salah ketik.

Contoh versi constexpr Anda dapat digunakan sebagai objek waktu kompilasi dan waktu proses.

template <typename Type>
class ConstValue
{
    public:
        constexpr ConstValue(const Type& val) : _value(val) {;}
        constexpr Type get() const {return _value;}
    protected:
        const Type _value;
};

int main(int argc, char* argv[])
{
    int x[ConstValue<int>(3).get()];
}
person Andy Prowl    schedule 18.01.2013