템플릿의 특정 전문화 금지
template <typename T>
T f(T t) {
return 2 * t + 3;
}
이 기능에는 문제가 없어 보입니다. 여러 유형에서 사용할 수 있습니다.
f(15)
는 33을 반환하고 T
는 int
, f(2.3)
는 7.6을 반환하고 T
는 double
등입니다. T
가 덧셈을 지원하는 유형이 아닌 경우 곱하면 컴파일러 오류가 발생합니다. f("hello")
의 예:
error: invalid operands to binary expression ('int' and 'const char *')
그럼에도 불구하고 계획하지 않은 경우가 발생할 수 있습니다. 예를 들어,
f(true)
는 유효하고 경고를 발생시키지 않으며 true
를 반환합니다(사실, 부울로 변환된 5, 즉 true
)를 반환합니다.컴파일 타임에 거부
f<bool>
하는 방법을 시도해 보겠습니다. 템플릿의 특정 전문화를 금지하는 가능성이 C++ 버전과 함께 발전했음을 알 수 있습니다. 각 기술에 대해 컴파일러 clang 가 f(true)
에 대해 생성하는 오류를 보여드리겠습니다.여기서 내 목적은 덧셈과 곱셈을 지원하지 않는 유형을 적절하게 처리하는 것이 아니라 특정 전문화를 금지하는 것입니다.
=전문화 시 삭제
C++11부터
첫 번째 해결책은
f()
에 대한 T == bool
의 전문화를 명시적으로 삭제하는 것입니다.template<>
bool f(bool) = delete;
error: call to deleted function 'f'
note: candidate function [with T = bool] has been implicitly deleted
static_assert
두 번째 솔루션은
T
의 f()
에 정적 어설션을 추가하는 것입니다. static_assert
는 C++11에 도입되었습니다. 표준 라이브러리에는 T
가 bool
가 아닌지 확인하는 두 가지 기술이 있습니다. 하나는 C++11이고 다른 하나는 C++17입니다.C++11부터
C++11이 도입되었습니다the template structure
std::is_same
, 이는 여러분이 생각하는 것과 정확히 일치합니다.#include <type_traits>
template <typename T>
T f(T t) {
static_assert(not std::is_same<T, bool>::value, "T cannot be bool");
return 2 * t + 3;
}
error: static_assert failed due to requirement '!std::is_same<bool, bool>::value' "T cannot be bool"
C++17부터
C++17은 변수 템플릿
std::is_same_v<U, V>
을 std::is_same<U, V>::value
의 바로 가기로 도입했습니다.#include <type_traits>
template <typename T>
T f(T t) {
static_assert(not std::is_same_v<T, bool>, "T cannot be bool");
return 2 * t + 3;
}
error: static_assert failed due to requirement '!std::is_same_v<bool, bool>' "T cannot be bool"
참고: variable templates were introduced in C++14 .
개념
C++20부터
Concepts은 C++20의 가장 큰 특징 중 하나입니다.
T
가 bool
인 것을 금지하는 개념에는 두 가지 가능성이 있습니다.require 절과 함께
#include <concepts>
template <typename T> requires (not std::same_as<T, bool>)
T f(T t) {
return 2 * t + 3;
}
error: no matching function for call to 'f'
note: candidate template ignored: constraints not satisfied [with T = bool]
note: because '!std::same_as<_Bool, _Bool>' evaluated to false
커스텀 컨셉으로
#include <concepts>
template <typename T, typename U>
concept different_than = not std::same_as<T, U>;
template <different_than<bool> T>
T f(T t) {
return 2 * t + 3;
}
error: no matching function for call to 'f'
note: candidate template ignored: constraints not satisfied [with T = bool]
note: because 'different_than<_Bool, _Bool>' evaluated to false
note: because '!std::same_as<_Bool, _Bool>' evaluated to false
결론
제 생각에는
=delete
다른 기술에 비해 장점이 없습니다. 사용자 정의 오류 메시지를 작성할 수 있기 때문에 static_assert
를 좋아하지만 하루가 끝나면 개념이 더 명확한 의미를 갖기 때문에 개념이 더 크다고 생각합니다. 그리고 그 정상: 템플릿 매개변수의 제약 조건을 정확히 표현하기 위해 만들어졌습니다.👇🏻 어떤 기술을 사용/선호하는지, 그리고 그 이유를 댓글로 남겨주세요 😃
추신: 이 기사의 아이디어는 👍🏻의 토론에서 비롯되었습니다.
Reference
이 문제에 관하여(템플릿의 특정 전문화 금지), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/pgradot/forbid-a-particular-specialization-of-a-template-4348텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)