저는 CLion 2016.3.4에서 개발중인 C++ 14 프로젝트를 가지고 있으며, 코드의 한 조각으로 인해 검사 오류가 발생했습니다.SFINAE 제거, Constexpr 및 함수 템플릿 : 선언과 정의를 별도로 유지할 수 있습니까?
#include <iostream>
#include <type_traits>
#include <system_error>
using error_id_type = int;
template <typename T> using enable_if_condition_enum_t =
typename std::enable_if<std::is_error_condition_enum<T>::value, T>::type;
// Declaration
template <typename T, typename = enable_if_condition_enum_t<T>>
constexpr error_id_type error_enum_to_int(T elem) noexcept;
// Definition
template <typename T, typename = enable_if_condition_enum_t<T>>
constexpr error_id_type error_enum_to_int(T elem) noexcept {
return static_cast<error_id_type>(elem);
};
int main(void) {
error_id_type condition = error_enum_to_int(std::errc::owner_dead); // inspection error here
switch (condition) {
case error_enum_to_int(std::errc::address_in_use): break; // inspection error here
default: break;
}
std::cout << condition << std::endl;
return 0;
}
CLion이 error_enum_to_int
의 모든 호출 발생 나에게 Call to "error_enum_to_int" is ambiguous
을 제공합니다 : 나는 문제를 재현하기위한 최소한의 코드를 만들었습니다. 그런 종류의 사용에 실제로 어떤 문제가 있습니까? ,
- 이 선언을 삭제하고 (작품 만의 정의를두고,하지만 난 같은 컴파일 단위에서 다른 위치에서 그들을 유지하고 싶었 :
어떤 것들은 내가 시도했지만 그건 정말 이럴 해결되지 않습니다 가능한 경우);
- SFINAE 템플릿 인수를 삭제합니다 (작동하지만 모든 유형에 사용할 수 있습니다. 의도는 아닙니다).
enable_if_condition_enum_t<T>
으로 대체하면T
인수가됩니다 (작동하지 않아서 컴파일 및 검사 오류가 완전히 수정되었습니다).
코드는 g++ (GCC) 6.3.1 20170306
에 수정없이 잘 컴파일되어 실행됩니다. 불행히도, 나는 지금 이것을 시험해보기 위해 다른 컴파일러에 접근 할 수 없지만, 이것이 표준의 휴대용 C++ 11이라고 생각한다.
물론 언제나 static_cast<some_enum_class>(some_int)
에 대한 옵션이 있지만,이 코드 스 니펫에 어떤 문제가 있는지 구체적으로 알고 싶습니다.
내 질문은 : 이것은 내 IDE의 버그이며, 실제로 인식하지 못하는 언어의 경우이거나 정말 멍청한 뭔가를하고있는 것입니까 (: D)?
내 추론
내가 잘못하면 저를 시정하십시오.
자체 선언은 함수 템플릿 인 경우에도 정의가 아닙니다. 함수 템플릿 자체는 인스턴스화 될 때까지 실제로 함수가 아닙니다. 그럼에도 불구하고 컴파일러는 두 함수가 동일한 컴파일/변환 단위에있는 한 동일한 함수 템플릿의 두 가지 발생이 있고 다른 하나를 혼동하지 않는 것을 볼 수 있어야합니다. CLion (또는 clang의 정적 분석기)은 선언을 정의로 간주하고 다른 것으로 해석합니다. 그리고 두 가지 모두 템플릿이기 때문에 어떤 것을 인스턴스화할지 혼란 스럽습니다.
선언과 정의가 모두 같은 컴파일 단위에 있음에 유의하십시오. 또한 constexpr
은 inline
을 의미하므로 하나의 정의 규칙이 계속 적용됩니다. 또한, 인수로 사용되는 열거 형을 std::error_condition
열거 형으로 선언하지 않은 경우 SFINAE 기반 제거에 enable_if_condition_enum_t
을 사용합니다.
UPDATE
@Angew's answer에 따라, 여기에 올바른 선언과 error_enum_to_int
의 정의입니다.
// Declaration
template <typename T, typename = enable_if_condition_enum_t<T>>
constexpr error_id_type error_enum_to_int(T elem) noexcept;
// Definition
template <typename T, typename>
constexpr error_id_type error_enum_to_int(T elem) noexcept {
return static_cast<error_id_type>(elem);
};
@ 앤그 정확한! aswer를 만들어서 받아 들일 수 있을까요? –