52 votes

Une classe ne peut-elle pas avoir des instances membres statiques constexpr d'elle-même ?

Ce code me donne type incomplet erreur. Quel est le problème ? Il n'est pas permis pour une classe d'avoir instances membres statiques de lui-même ? Existe-t-il un moyen d'obtenir le même résultat ?

struct Size
{
    const unsigned int width;
    const unsigned int height;

    static constexpr Size big = { 480, 240 };

    static constexpr Size small = { 210, 170 };

private:

    Size( ) = default;
};

4 votes

Est-ce que vous demandez spécifiquement constexpr membres statiques ?

0 votes

@PiotrSkotnicki Oui. Supprimer le mot-clé ne fait pas fonctionner le système de toute façon.

2 votes

Une fois que vous avez supprimé le mot-clé, vous pouvez l'initialiser à l'extérieur de la classe, lorsque c'est déjà un type complet.

64voto

Brian Points 15388

Une classe es peut avoir un membre statique du même type. Cependant, une classe est incomplète jusqu'à la fin de sa définition, et un objet ne peut être défini avec un type incomplet. Vous pouvez déclarer un objet de type incomplet, et le définir plus tard là où il est complet (en dehors de la classe).

struct Size
{
    const unsigned int width;
    const unsigned int height;

    static const Size big;
    static const Size small;

private:

    Size( ) = default;
};

const Size Size::big = { 480, 240 };
const Size Size::small = { 210, 170 };

voir cela ici : http://coliru.stacked-crooked.com/a/f43395e5d08a3952

Cela ne fonctionne pas pour constexpr cependant.

1 votes

Pensez-vous que cela ne fonctionne pas pour constexpr parce qu'ils sont interdits par la norme ou à cause d'un bug du compilateur ?

10 votes

@nyarlathotep108 Cela ne fonctionne pas parce qu'une static constexpr doit être initialisé en ligne.

1 votes

Qu'en est-il cette approche ?

46voto

Mike Kinghan Points 4567

Existe-t-il un moyen d'obtenir le même résultat ?

Par "le même résultat", voulez-vous dire spécifiquement le constexpr -de Size::big y Size::small ? Dans ce cas, ceci serait peut-être assez proche :

struct Size
{
    const unsigned int width = 0;
    const unsigned int height = 0;

    static constexpr Size big() {
        return Size { 480, 240 };
    }

    static constexpr Size small() {
        return Size { 210, 170 };
    }

private:

    constexpr Size() = default;
    constexpr Size(int w, int h )
    : width(w),height(h){}
};

static_assert(Size::big().width == 480,"");
static_assert(Size::small().height == 170,"");

6voto

benb Points 111

Comme solution de rechange, vous pouvez utiliser une classe de base distincte dont la définition est complète lors de la définition des constantes dans la classe dérivée.

struct size_impl
{
//data members and functions here
    unsigned int width;
    unsigned int height;
};

struct size:  public size_impl
{
//create the constants as instantiations of size_impl
    static constexpr size_impl big{480,240};
    static constexpr size_impl small{210,170};

//provide implicit conversion constructor and assignment operator
    constexpr size(const size_impl& s):size_impl(s){}
    using size_impl::operator=;

//put all other constructors here
};

//test:
constexpr size a = size::big;

Vous pouvez placer la classe de base dans un espace de nom distinct pour masquer sa définition si vous le souhaitez.

Le code se compile avec clang et gcc

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X