2017-04-24 6 views
10

클래스에서 static constexpr을 사용하면 클래스 정의 (참조 : this question) 외부에 코드가 필요하기 때문에 enum { my_const = 123; }으로 내 상수를 정의하는 데 익숙합니다. 그러나 기능 기관에서는 어떨까요? 나는 그래서 내함수 내에서 상수로 선호하는 것은? constexpr const 또는 enum?

int foo(int x) 
{ 
    enum : int { bar = 456 }; 
    return x + bar; 
} 

와 시간 뒤에 바보 해요 여부를 최근에 내가 몰래 봤는데 사람들은 (심지어 실제로 const에 귀찮게하지 않음)의 기능에 constexpr 변수를 가지고, 나는 궁금해서, 내 질문 : constexpr 변수가 아닌 함수 본문에서 enum을 사용하면 어떤 이점이 있습니까?

+3

C++ 1z가 나오고 (아마도 이번 7 월), 주류 컴파일러 지원을 얻게 될 때 자동으로 인라인 될 것이므로 클래스에서'static constexpr' 변수를 사용할 수 있습니다. 그러나 함수의 경우 상수에 대한 함수 안에'enum '을 선언한다는 것을 의미합니까? –

+0

@ 대니얼 : 예, 편집을 참조하십시오. – einpoklum

+3

함수 본체 안에 아무런 이점도 없다는 것이 거의 확실합니다. (비 정적 변수는 링키지가 필요없고 정적 변수는 함수 자체의 것을 공유 할 수 있습니다.) 실제로 C++ 표준에서는 허용되지 않습니다. (비록 어떤 컴파일러가 그것을 확장으로 허용 할지라도). 특히 g ++ (버전 6.3)에서 코드를 컴파일 할 수 없습니다. 나는이 문제에 대해 논평 대신 답을 내릴 수있는 확신이 없지만 그것이 틀렸다면 나는 놀랄 것이다. –

답변

18

constexpr int bar = 456; 인 경우 우연히 또는 의도적으로 ODR이 있음을 나타낼 수 있습니다. enum : int { bar = 456 };으로는 불가능합니다.

어느 쪽이든 이점이있을 수도 있고 그렇지 않을 수도 있습니다. 예를

int baz(int const* ptr) { 
    if (ptr) return 7; return -1; 
} 
int foo(int x) 
{ 
    // enum : int { bar = 456 }; 
    constexpr int bar = 456; 
    return x + baz(&bar); 
} 

enum 버전은 컴파일되지 않습니다 들어

constexpr int 하나를 수행합니다. constexpr int은 lvalue 일 수 있고 열거 자 (나열된 열거 형 상수 중 하나)를 사용할 수 없습니다. constexpr int가 실제로 int 동안

열거

값은 실제로 int 아니다. 이 값을 전달하면 문제가 될 수 있습니다.

template<class T> 
void test(T) { 
    static_assert(std::is_same<T,int>::value); 
} 

하나는 테스트에 합격합니다. 다른 쪽은 그렇지 않습니다.

토큰을 사용하는 방법에 따라 장점, 단점 또는 의미없는 버릇이 될 수 있습니다. @ Yakk의를 기반으로

+0

ODR이 무엇인지는 알지만, 여기에 "ODR- 존재"가 무엇을 의미하는지 확신 할 수 없습니다. 컴파일하지 않는 열거 형 버전에 대해서는 AFAIK가 실제로 컴파일되지 않아야합니다. 당신이 말했듯이, 나는'int'라는 bar라는 이름의 변수를 갖고 싶지 않습니다. 단지 컴파일 타임에'int'처럼 행동하는 값입니다. 실제로 두 번째 버전이 컴파일되면 놀랍습니다. 즉, 막대가 메모리에 할당 된 공간을 가져야 함을 의미합니다. – einpoklum

+2

컴파일러가 이것이 필요하다고 결정하면 메모리에 공간이 할당됩니다. 주소를 쓰지 않으면 이럴 가능성이 희박합니다. 컴파일러가 어딘가에 번호를 저장하려고한다고해도 아마 레지스터를 사용할 것이고 대개 값을 저장하고 싶지 않을 것입니다. 'constexpr int'는 대부분의 경우 컴파일 타임에만 존재하는 값입니다. –

+0

@einpok ODR은 값의 가치가 아니라 변수의 정체성 *이 필요하다는 것을 의미합니다. 'constexpr' 값은 컴파일 타임에 계산 될 수있는 값을 가지고 있지만, 역시 ID를 가질 수 있습니다; 열거 형 값은 ID를 가질 수 없습니다. 정체성의 존재는 "실제로 존재하는 메모리"와 비슷하지만 그다지 중요하지 않습니다. 때때로 정체성을 가진 것들은 자신의 기억을 최대한 활용할 수 있습니다. "정체성"은 표준에서 나온 용어는 아니며 단지 설명하려고 시도한 것입니다. – Yakk

1

한 - 라이너 (그러나 이것은 내 자신의 포획이) :

당신이 당신의 일정한 런타임에 "변수"로 존재하는 것을 허용 할 수없는 경우 필요할 수 있습니다 enum 기반의 상수를 사용하여

. 열거 형을 사용하여 무엇을하든 상관없이 주소가없고 메모리 공간이 차지하지 않습니다. 컴파일러 최적화로 인해 발생하지 않을 수도 있습니다.

다른 경우에는 다른 하나보다 선호하는 매력적인 이유가없는 것처럼 보입니다.

+0

odr-used가 아닌 상수를위한 공간을 차지하는 "변수"가 없습니다. 이것은 최적화에 의존하지 않고 언어에 의해 보장됩니다 (표준은 "메모리 공간 차지"에 대해 실제로 말하지 않으므로 정확하게 말하지 않습니다). –

+0

낭비 된 공간에 대한 잘못된 (IMHO) 우려로 인해 코드를 흐리게 처리하고 새로운 유형 (열거 형)을 발명하면 잘못된 문제에 초점을 맞추고 있습니다. [열거 형을 사용하여 관련 명명 된 상수 집합을 나타냅니다.] (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Renum-set) 및 [이름없는 열거 형 피하기] (https : // github. ("정수형 상수를 지정하는 편리한 대체 방법이 있기 전에 작성된 코드에는 이러한 코드가 드물지 않습니다. 대신 대체 : constexpr 값을 사용하십시오.") –

+1

@ cppCoreGuidelines/blob/master/CppCoreGuidelines.md # Renum-unnamed Jonathan Wakely : 이것이 잘못되었는지 여부는 문맥에 달려 있습니다. 누군가가'constexpr' 필드를위한 공간 할당을 유발할 수 있으며, 다른 메모리 레이아웃은 다른 곳에서 컴파일 된 코드와의 비 호환성을 초래할 수 있습니다. – einpoklum