2017-01-16 8 views
1

я наткнулся на код, как это от программиста я очень уважаю:Преимущество замены статических членов константные статические функции-члены

class BigClass { 
    using MyId = uint32_t; 
    static constexpr MyId INVALID_ID() { return std::numeric_limits<MyId>::max();}; 
    class SmallClass { 
    /* Constructor, etc. */ 
    MyId id = INVALID_ID(); /* Default value */ 
    }; 
}; 

Есть ли очевидное преимущество для определения INVALID_ID() как функцию вместо того, чтобы как статическая переменная const?

Вопрос static constexpr variable vs function - это точно тот же вопрос, который у меня был (в качестве примера я использовал uint32_t), но я также задаю вопрос для других типов). Однако я не удовлетворен ответом на этот вопрос. Прочитав некоторые из ответов здесь, я считаю, что есть больше преимуществ для использования функций, чем возможность легко шаблонов.

+0

Ну, так как это не статическая переменная-член, ее не нужно определять вне класса. – NathanOliver

+1

Статические константы @ NathanOliver IIRC не нуждаются в определении до тех пор, пока они не используются ODR. – Quentin

+0

@Quentin Typo фиксированный. Они могут использовать его в этом контексте. – NathanOliver

ответ

1

Одна из причин заключается в том, что в этой форме нет необходимости определять статический элемент вне класса, который в случаях, когда класс реализуется внутри заголовка, может быть нежелательным.

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

+0

Ну, так как это постоянная интегрального типа, в любом случае нет необходимости определять ее вне класса. Очевидно, что он не должен использоваться как lvalue и до тех пор, пока он не используется lvalue, определение не требуется. – AnT

+0

По-моему, по-прежнему хорошая практика – ZivS

+0

Противоположность, если статическая константа предназначена для использования только как rvalue, тогда * not *, определяющая ее, является хорошей практикой - она ​​предотвращает злоупотребление ею как lvalue. Предоставление определения необязательно было значительным и долгожданным дополнением к спецификации C++. – AnT

-1

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

+0

Вопрос был задан здесь: https://stackoverflow.com/questions/16287776/static-constexpr-variable-vs-function?noredirect11&lq=1 –

+0

Объявление предназначено для функции constexpr которые имеют нулевое динамическое вычисление.Идентификатор скорее увидит constexpr что-либо в любом другом объявлении. – ZivS

1

Это связано с безопасностью потока и фиаско порядка статической инициализации. Если бы существовали две взаимозависимые статические переменные, которые определены в отдельных единицах перевода (одному нужно значение другого для построения), нет способа гарантировать порядок, в котором они будут инициализированы.

Использование функции обертки и C++ 11 гарантирует, что компилятор разместит необходимые блокировки потоков вокруг своей инициализации, функция local static сделает параллельные вызовы этой функции, ожидая инициализации переменной до ее продолжения.

+0

следует изменить забыть сделать в * Это нужно забыть с помощью безопасности потока и статического инициализационного порядка фиаско *? – NathanOliver

+0

Да, действительно, клавиатура телефона не имеет получилось намного лучше, угадывая, что я хочу напечатать ... – rubenvb

+0

Хорошо, я просто хотел проверить, если вы разделили на разные предложения вместе. – NathanOliver

1

Одна из проблем, люди пытаются решить путем замены класса статического Постоянными членами с функциями являются ошибки компоновщика.

Например:

struct A { 
    static constexpr int a = 1; 
}; 

void foo(int const&); 

foo(A::a); // Linker error: A::a. 

Правильное решение не принимать указатель или ссылку на A::a (если обеспечивая определение из-строки из A::a нежелательно):

void foo(int); 
+0

Вы можете взять указатель. Просто нужно определить 'A :: a'. –

+0

@NO_NAME Определение «A :: a» может быть нежелательным. –

2

Я могу видеть только одну истинную разницу за пределами простых применений кодирования: статическая константная переменная должна быть определена только в том случае, если она используется odr (используется в функции, использующей ref, например ...). Проблема в том, что если это правило не соблюдается, вы получаете ошибку времени ссылки, и программисты могут тратить время на поиск после того, какая проблема на самом деле.

Когда вы используете функцию таким образом, и пытаетесь передать ее в качестве вызова функции функции, требующей ref, ошибка времени компиляции сразу же появится на лицевой стороне программиста с явным сообщением об ошибке. Поэтому я бы сказал, что это больше подходит для будущих разработчиков ...

+0

Вызов функции undefined может быть скомпилирован так же, как использование объявленного статического глобального. Оба результата приводят к ошибкам компоновщика. – rubenvb

 Смежные вопросы

  • Нет связанных вопросов^_^