아침, 여러분!constexpr 고유 ID, clang으로 컴파일되지만 gcc로 컴파일되지 않음
이벤트 대기열을 리팩토링하고 있습니다. 컴파일 할 때 이벤트 ID를 고유하게 만들 수 있는지 살펴 보려고합니다. 내가 clang 4.0.0에서 작동하지만 g ++ 6.3.1에서 컴파일 오류가 발생합니다.
아이디어는 정적 멤버 변수의 주소를 사용하여 개별 유형을 고유하게 식별 한 다음 태그 지정을 사용하여 클래스 템플릿에서 이러한 고유 한 유형을 생성하는 것입니다.
정적 멤버의 주소를 유형 ID로 사용하는 것은 비교적 일반적인 기술이지만 템플릿을 사용하면 ODR을 알 수 없다는 것을 의미합니다. MSN은 이것이 유효한 접근 방법임을 제안하기 위해 여기에 표준을 인용했습니다. Compile-time constant id
제 문제는이 constexpr입니다. constexpr을 제거하고 이것을 런타임에 테스트하면 모든 것이 예상대로 작동합니다. 그러나이 constexpr을 수행하면 g ++에서 정적 어설 션이 실패합니다. "error : 정적 어설 션에 대한 상수가 아닌 조건"입니다.
- 포인터 산술 또는 호출 비 constexpr 회원 :, 모든 constexpr 더 포인터 연산이 없습니다 Why is this not a constant expression? 입니다
는 꽤 연구 한 후, 가장 유사한 문제가 보인다.
- constexpr 표현식에서 reinterpret_cast 사용 : Constexpr pointer value 이것은 포인터를 사용하지만 형식은 그대로입니다. 전환이 적용되지 않습니다.
- 불완전한 유형 사용 : Why is this constexpr static member function not seen as constexpr when called? 이 유형이 완전하다고 확신합니다.
이러한 문제의 대부분은 g ++이 부적합하고 clang ++ 오류입니다. 이것은 그 반대입니다.
내가 곤혹 스럽다. 여기에 정적에 ++ g에 컴파일되지 않습니다 어떤 주석 내가 뭘 찾았는지의 제거 다운 버전이의 주장 :
~$ clang++ --version
clang version 4.0.0 (tags/RELEASE_400/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
~$ clang++ -std=c++14 -c example.cpp
~$ g++ --version
g++ (GCC) 6.3.1 20170306
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
example.cpp:14:1: error: non-constant condition for static assertion
static_assert(&t<tag_0>::storage != &t<tag_1>::storage, "This does not compile with g++.");
^~~~~~~~~~~~~
example.cpp:14:34: error: ‘((& t<tag_0>::storage) != (& t<tag_1>::storage))’ is not a constant expression
static_assert(&t<tag_0>::storage != &t<tag_1>::storage, "This does not compile with g++.");
~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
example.cpp:15:1: error: non-constant condition for static assertion
static_assert(!(&t<tag_0>::storage == &t<tag_1>::storage), "Neither does this.");
^~~~~~~~~~~~~
example.cpp:15:15: error: ‘((& t<tag_0>::storage) != (& t<tag_1>::storage))’ is not a constant expression
static_assert(!(&t<tag_0>::storage == &t<tag_1>::storage), "Neither does this.");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
example.cpp:19:1: error: non-constant condition for static assertion
static_assert(id_0 != id_1, "This also does not.");
^~~~~~~~~~~~~
example.cpp:19:20: error: ‘((& t<tag_0>::storage) != (& t<tag_1>::storage))’ is not a constant expression
static_assert(id_0 != id_1, "This also does not.");
~~~~~^~~~~~~
~$
나 ': 여기
template <typename tag>
struct t
{
constexpr static char const storage{};
};
template <typename tag>
constexpr char const t<tag>::storage;
struct tag_0 {};
struct tag_1 {};
static_assert(&t<tag_0>::storage == &t<tag_0>::storage, "This always compiles.");
static_assert(&t<tag_1>::storage == &t<tag_1>::storage, "So does this.");
static_assert(&t<tag_0>::storage != &t<tag_1>::storage, "This does not compile with g++.");
static_assert(!(&t<tag_0>::storage == &t<tag_1>::storage), "Neither does this.");
constexpr auto id_0 = &t<tag_0>::storage; // This does.
constexpr auto id_1 = &t<tag_1>::storage; // This does.
static_assert(id_0 != id_1, "This also does not.");
그리고 컴파일러 출력입니다 내가 왜 constexpr을 이해하는지와 충돌하기 때문에이 특정 접근법이 gcc로 컴파일되지 않는 이유가 궁금하다.
(이 좋은 디자인의 경우 내가 물어 아니에요, 또는 이러한 목표를 달성 할 수있는 다른 방법이 있는지. 나는이 작업을 수행 할 수있는 다른 방법이있다.)
감사합니다!
편집 : 두 컴파일러로 컴파일 않습니다 템플릿이없는 비교 예는 다음과 같을 수 있습니다 당신은 constexpr 반원에 두 가지 포인터를 비교하기 위해 노력하고 있으며 표준에 지정되지 않은
struct t1
{
static constexpr int const v{};
};
constexpr int t1::v;
struct t2
{
static constexpr int const v{};
};
constexpr int t2::v;
static_assert(&t1::v != &t2::v, "compiles with both");
g ++ 7.1.1에서도 마찬가지입니다. –