SFINAE
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
SFINAE (Substitution Failure Is Not An Error)는 C++ 템플릿 메커니즘의 특징으로, 템플릿 인수를 대체하는 과정에서 오류가 발생해도 컴파일 오류로 이어지지 않고 다른 오버로드를 선택하거나 컴파일을 계속 진행하도록 하는 기술이다. 이는 헤더 파일 포함 등으로 인해 템플릿 선언이 중복될 때 발생하는 문제를 방지하기 위해 도입되었지만, 컴파일 시간에 템플릿 인수의 속성을 검사하는 데 널리 활용된다. SFINAE는 함수 오버로딩과 결합하여 특정 타입에 특정 멤버가 존재하는지 확인하는 등의 용도로 사용되며, C++11 이후 `void_t`와 같은 기능을 통해 더욱 간결하게 활용할 수 있다. Boost 라이브러리에서도 `boost::enable_if`를 통해 SFINAE를 활용한다.
더 읽어볼만한 페이지
- C++ - 헤더 파일
헤더 파일은 프로그래밍 언어에서 코드 재사용성, 모듈화, 컴파일 시간 단축에 기여하며 함수 프로토타입, 변수 선언 등을 포함하고 `#include` 지시어로 소스 코드에 포함되어 사용되는 파일이다. - C++ - 소멸자 (컴퓨터 프로그래밍)
소멸자는 객체가 메모리에서 제거되기 직전에 호출되는 멤버 함수로, 객체 자원 해제 및 정리 작업을 수행하며, C++ 등 여러 언어에서 구현되고 메모리 누수 방지에 기여한다. - 소프트웨어 디자인 패턴 - 모델-뷰-컨트롤러
모델-뷰-컨트롤러(MVC)는 소프트웨어 디자인 패턴으로, 응용 프로그램을 모델, 뷰, 컨트롤러 세 가지 요소로 분리하여 개발하며, 사용자 인터페이스 개발에서 데이터, 표현 방식, 사용자 입력 처리를 분리해 유지보수성과 확장성을 높이는 데 기여한다. - 소프트웨어 디자인 패턴 - 스케줄링 (컴퓨팅)
스케줄링은 운영 체제가 시스템의 목적과 환경에 맞춰 작업을 관리하는 기법으로, 장기, 중기, 단기 스케줄러를 통해 프로세스를 선택하며, CPU 사용률, 처리량 등을 기준으로 평가하고, FCFS, SJF, RR 등의 알고리즘을 사용한다.
SFINAE | |
---|---|
'SFINAE (Substitution failure is not an error)' | |
정의 | 템플릿 인스턴스화 과정에서 유효하지 않은 대체를 시도할 경우, 컴파일 오류를 발생시키는 대신 해당 후보를 제거하는 C++의 특징. |
설명 | 함수 템플릿 오버로딩 해결에 사용되며, 특정 템플릿이 주어진 인수 집합에 대해 유효한지 여부에 따라 다르게 동작하도록 함. |
목적 | 컴파일 시간에 템플릿 코드를 조건부로 활성화하거나 비활성화하는 메커니즘을 제공하여 더 유연하고 일반적인 코드를 작성할 수 있도록 함. |
예시 | 특정 멤버 함수나 형식이 존재하지 않는 클래스에 대해 템플릿을 특수화하는 경우, SFINAE를 사용하여 해당 특수화를 제거하고 다른 오버로드를 선택할 수 있음. |
사용 예제 | |
멤버 존재 확인 | 클래스에 특정 멤버 함수가 있는지 여부에 따라 다른 코드를 실행. |
형식 특성 | 특정 형식의 특성(예: 정수형, 클래스형)에 따라 다른 템플릿을 선택. |
오버로드 해결 | 함수 오버로드 집합에서 가장 적합한 함수를 선택하는 데 사용. |
기술적 세부 사항 | |
대체 컨텍스트 | 템플릿 매개변수가 대체되는 동안 발생하는 오류는 SFINAE를 트리거함. |
오류 유형 | 유효하지 않은 형식, 존재하지 않는 멤버, 잘못된 표현식 등이 SFINAE를 유발할 수 있음. |
예외 | 함수의 본문이나 함수의 인스턴스화 이후에 발생하는 오류는 SFINAE의 영향을 받지 않으며, 일반적인 컴파일 오류로 처리됨. |
관련 기술 | |
템플릿 메타프로그래밍 | SFINAE는 컴파일 시간에 복잡한 논리를 수행하는 데 사용되는 템플릿 메타프로그래밍의 핵심 기술 중 하나임. |
`std::enable_if` | SFINAE를 사용하여 템플릿을 조건부로 활성화하거나 비활성화하는 데 사용되는 표준 라이브러리 템플릿. |
`decltype` | 표현식의 형식을 추론하는 데 사용되며, SFINAE와 함께 사용하여 형식에 따라 다른 코드를 실행할 수 있음. |
2. 예시
SFINAE 원칙이 실제 C++ 코드에서 어떻게 적용되고 활용되는지를 보여주는 몇 가지 대표적인 예시가 있다. SFINAE는 주로 템플릿 오버로딩 해결 과정이나 템플릿 메타프로그래밍 기법에서 중요한 역할을 수행한다.
가장 기본적인 활용 사례는 함수 템플릿 오버로딩 과정에서 특정 타입 조건을 만족하지 못하는 템플릿 후보를 컴파일 오류 없이 제외하는 것이다. 예를 들어, 템플릿 인수로 전달된 타입이 특정 멤버 타입이나 함수를 가지고 있지 않을 경우, 해당 멤버에 접근하려는 템플릿 함수는 SFINAE 규칙에 따라 조용히 오버로딩 후보에서 제외된다. 이를 통해 개발자는 다양한 타입에 대해 더 유연하고 안전한 템플릿 코드를 작성할 수 있다.
또한 SFINAE는 컴파일 시점에 타입의 특정 속성을 검사하는 템플릿 메타프로그래밍 기법의 핵심 원리로 사용된다. 예를 들어, 주어진 타입이 특정 `typedef`를 가지고 있는지, 특정 멤버 함수를 포함하는지 등을 컴파일 시간에 확인하여 조건부로 코드를 다르게 생성하거나 특정 기능의 사용 가능 여부를 판단하는 데 활용될 수 있다.
아래 하위 섹션에서는 이러한 SFINAE의 활용 예시를 구체적인 코드와 함께 더 자세히 다룬다.
- 기본 예제: SFINAE의 핵심 동작 원리를 보여주는 간단한 코드 예시를 통해 기본적인 개념을 설명한다.
- 타입 검사 예제: SFINAE를 이용하여 타입의 특정 속성(예: `typedef`의 존재 여부)을 컴파일 시간에 확인하는 기법과 그 발전 과정을 보여준다.
2. 1. 기본 예제
SFINAE는 "Substitution Failure Is Not An Error"의 약자로, C++ 템플릿 오버로딩 해결 과정에서 발생하는 특정 종류의 오류가 컴파일 오류로 이어지지 않는 원칙을 의미한다. 즉, 템플릿 인수를 특정 위치에 치환(substitution)하여 인스턴스화할 때 실패(failure)하더라도, 이것이 바로 컴파일 오류(error)가 되지는 않고(not an error), 해당 템플릿 후보를 오버로딩 후보 집합에서 조용히 제외하는 것을 말한다.[5]구체적으로 SFINAE는 다음과 같은 상황에서 적용된다.
# 함수 오버로딩 해결 과정에서,
# 템플릿 인수를 해당 매개변수 타입에 치환하여 만들어진 함수 시그니처가 후보 집합에 포함된다.
# 이때, 치환 과정에서 유효하지 않은 코드(예: 존재하지 않는 멤버 접근, 잘못된 타입 연산 등)가 발생하더라도,[6] C++ 표준에서 SFINAE가 적용되도록 규정한 경우에 한해,
# 해당 함수 템플릿은 컴파일 오류를 발생시키지 않고 단순히 후보 집합에서 제외된다.
만약 다른 유효한 후보 함수가 존재하여 오버로딩 해결이 성공하면, 프로그램은 정상적으로 컴파일되고 실행될 수 있다.
다음은 SFINAE의 기본적인 동작 방식을 보여주는 예제이다.
struct Test {
typedef int foo;
};
template
void f(typename T::foo) {} // 정의 #1: T 안에 foo 타입이 있어야 유효함
template
void f(T) {} // 정의 #2: 모든 타입 T에 대해 유효함
int main() {
f
f
return 0;
}
위 예제에서 `f
반면, `f
이처럼 SFINAE는 처음에는 관련 없는 템플릿 선언(예: 헤더 파일을 통해 포함된 선언) 때문에 의도치 않게 프로그램이 잘못된 형식으로 컴파일되는 것을 방지하기 위해 도입되었다. 하지만 개발자들은 이 동작을 이용하여 컴파일 시점에 타입의 속성을 검사하는 템플릿 메타프로그래밍 기법으로 유용하게 활용하고 있다.
2. 2. 타입 검사 예제
SFINAE는 원래 관련 없는 템플릿 선언이 존재할 때 프로그램 오류를 방지하기 위해 도입되었지만, 컴파일 시간에 타입의 속성을 확인하는 인트로스펙션 기법으로 유용하게 활용될 수 있음이 발견되었다. 특히 템플릿 인스턴스화 시점에 해당 템플릿 인수가 특정 조건을 만족하는지 검사하는 데 사용된다.예를 들어, SFINAE를 이용하면 특정 타입 내부에 원하는 typedef가 정의되어 있는지 컴파일 시간에 확인할 수 있다. 다음은 C++98/03 스타일의 구현 예시이다.
#include
template
struct has_typedef_foobar {
// 크기가 다른 두 타입 'yes'와 'no'를 정의한다.
// sizeof(yes)는 1, sizeof(no)는 2가 된다.
typedef char yes[1];
typedef char no[2];
// T 타입 내부에 'foobar'라는 typedef가 있으면 이 함수 템플릿이 선택된다.
template
static yes& test(typename C::foobar*); // 포인터 타입으로 받는 이유는 널 포인터(nullptr)를 인자로 넘기기 위함이다.
// 'foobar' typedef가 없거나 다른 이유로 위 함수 템플릿 선택에 실패하면,
// 이 함수 템플릿이 대신 선택된다. '...'는 모든 타입의 인자를 받을 수 있으며,
// 타입 변환 우선순위가 가장 낮아 첫 번째 함수가 가능하면 우선 선택된다.
template
static no& test(...);
// test
// sizeof(test
static const bool value = sizeof(test
};
struct foo {
typedef float foobar; // 'foobar' typedef를 가짐
};
int main() {
std::cout << std::boolalpha; // bool 값을 true/false로 출력
std::cout << has_typedef_foobar
std::cout << has_typedef_foobar
return 0;
}
만약 타입 T 안에 foobar라는 중첩 타입(typedef)이 정의되어 있다면, `typename C::foobar*` 형태의 인자를 받는 첫 번째 test 함수 템플릿이 성공적으로 인스턴스화되고, nullptr를 인자로 전달할 수 있게 된다. 이때 함수의 반환 타입은 yes& 이므로, sizeof(test
C++11에서는 std::true_type, std::false_type과 using 선언(타입 별칭), void_t (C++17 표준, C++11에서는 직접 정의 가능) 등을 활용하여 이 기법을 더 간결하게 구현할 수 있다.
#include
#include
// C++17의 std::void_t와 유사한 기능. 어떤 타입이든 void로 만든다.
// SFINAE를 유발시키는 용도로 사용된다.
template
using void_t = void;
// 기본 템플릿: T::foobar가 없거나 다른 이유로 아래 특수화 버전이 실패하면 선택됨.
template
struct has_typedef_foobar : std::false_type {}; // 결과로 false_type 상속
// 템플릿 특수화: T::foobar가 유효한 타입일 경우 이 버전이 선택됨.
// void_t
template
struct has_typedef_foobar
struct foo {
using foobar = float; // C++11 using 선언 사용
};
int main() {
std::cout << std::boolalpha;
std::cout << has_typedef_foobar
std::cout << has_typedef_foobar
return 0;
}
C++17에서는 이러한 타입 특성 검사 기법이 std::is_detected 와 같은 형태로 표준 라이브러리에 포함되어 더욱 간편하게 사용할 수 있다.
#include
#include
// 검사하고자 하는 표현식(T::foobar 타입)을 정의
template
using foobar_t = typename T::foobar; // C++11 using 활용
struct foo {
using foobar = float;
};
int main() {
std::cout << std::boolalpha;
// std::is_detected<검사할 표현식, 검사할 타입>::value 형태로 사용
std::cout << std::is_detected
std::cout << std::is_detected
return 0;
}
(참고: std::is_detected는 C++20 표준 라이브러리 유틸리티로 정식 포함될 예정이었으나, 최종적으로 포함되지 않고 Library Fundamentals TS v2 등에 남아있다. 실제 사용 시에는 컴파일러 및 표준 라이브러리 버전에 따라 지원 여부가 다를 수 있다.)
Boost 라이브러리에서는 boost::enable_if[7] 와 같은 유틸리티들이 SFINAE 원리를 기반으로 구현되어, 조건부 컴파일 및 템플릿 메타프로그래밍에 널리 사용된다.
3. C++11에서의 간소화
C++11 표준은 SFINAE(Substitution Failure Is Not An Error) 기법을 더 간결하게 사용할 수 있는 방법을 도입했다. 이전 버전의 C++에서 SFINAE를 구현하기 위해 사용되던 복잡한 기법들, 예를 들어 `sizeof` 연산자를 활용한 트릭 대신, 더 직관적인 방법을 제공한다.
주요 간소화 방법 중 하나는 `void_t`라는 별칭 템플릿(alias template)을 활용하는 것이다. `void_t`는 어떤 타입 인자들을 받더라도 항상 `void` 타입을 나타내는 간단한 템플릿이다. 이를 이용하면 특정 타입 표현식(예: 멤버 타입의 존재 여부)이 유효한지를 컴파일 시간에 검사하는 코드를 훨씬 단순하게 작성할 수 있다.
예를 들어, 타입 `T`가 `foobar`라는 중첩 타입을 가지고 있는지 확인하는 코드는 `void_t`를 사용하여 다음과 같이 간결하게 표현될 수 있다. (상세 구현 및 설명은 하위 섹션 참조)
#include
// 어떤 타입 인자든 void로 변환하는 별칭 템플릿
template
using void_t = void;
// 기본 템플릿: T::foobar가 유효하지 않으면 이 템플릿이 선택됨 (결과는 false)
template
struct has_typedef_foobar : std::false_type {};
// 템플릿 특수화: T::foobar가 유효한 타입 표현식이면 void_t
template
struct has_typedef_foobar
이러한 `void_t`를 이용한 기법은 C++17에서 `std::is_detected`라는 이름으로 표준 라이브러리에 포함되어 더욱 발전했다. ([http://en.cppreference.com/w/cpp/experimental/lib_extensions_2 라이브러리 기본 v2 (n4562)] 제안 참고) 이는 SFINAE를 활용한 타입 검사를 더욱 표준적이고 가독성 높게 만들어 주었다. (상세 내용은 하위 섹션 참조)
한편, 부스트(Boost) 라이브러리에서는 이미 C++11 이전부터 `boost::enable_if`[3] 와 같은 도구를 통해 SFINAE를 적극적으로 활용하여 템플릿 메타프로그래밍에서 조건부 컴파일 등의 기능을 구현해왔다.
3. 1. void_t 사용
C++11에서는 템플릿 메타프로그래밍에서 타입 특성을 검사하는 SFINAE 기법을 더 간결하게 사용할 수 있도록 `void_t` 라는 별칭 템플릿(alias template)을 활용할 수 있다. `void_t`는 어떤 타입 인자들을 받더라도 항상 `void` 타입을 나타낸다.#include
#include
// 어떤 템플릿 인수든 void가 된다.
template
using void_t = void;
// 기본 템플릿: T에 foobar 타입 정의가 없으면 이 템플릿이 선택됨
template
struct has_typedef_foobar : std::false_type {};
// 템플릿 특수화: T::foobar가 유효한 타입 표현식이면 void_t
template
struct has_typedef_foobar
struct foo {
using foobar = float; // foo 구조체는 foobar 타입을 가지고 있음
};
int main() {
std::cout << std::boolalpha;
// int 타입에는 foobar 멤버 타입이 없으므로 false 출력
std::cout << has_typedef_foobar
// foo 구조체에는 foobar 멤버 타입이 있으므로 true 출력
std::cout << has_typedef_foobar
return 0;
}
위 코드에서 `has_typedef_foobar
C++17에서는 이 기법이 `std::is_detected`라는 이름으로 표준 라이브러리에 포함되어 더욱 간결하게 사용할 수 있게 되었다. [http://en.cppreference.com/w/cpp/experimental/lib_extensions_2 라이브러리 기본 v2 (n4562)] 제안에서 표준화된 이 감지 관용구(detection idiom)를 사용하면 위 코드를 다음과 같이 작성할 수 있다.
#include
#include
// 검사하고자 하는 표현식 (T::foobar 타입)을 정의하는 별칭 템플릿
template
using has_typedef_foobar_t = typename T::foobar;
struct foo {
using foobar = float;
};
int main() {
std::cout << std::boolalpha;
// std::is_detected
// int 타입으로 has_typedef_foobar_t
std::cout << std::is_detected
// foo 타입으로 has_typedef_foobar_t
std::cout << std::is_detected
return 0;
}
`std::is_detected`는 첫 번째 템플릿 인자로 주어진 '연산(Operation)' 템플릿을 나머지 인자들로 적용했을 때 유효한 표현식인지 여부를 `std::true_type` 또는 `std::false_type`으로 알려준다. 이를 통해 `void_t`를 직접 사용하는 것보다 더 직관적으로 타입 특성을 검사할 수 있다.
3. 2. is_detected 사용 (C++17)
C++17 표준에서는 타입 검사를 위한 `std::is_detected`와 같은 도구를 제공하여 SFINAE 기법을 더 직관적이고 간결하게 사용할 수 있게 되었다. 이는 Library Fundamentals TS v2에서 제안된 탐지 관용구(detection idiom)가 표준 라이브러리에 반영된 결과이다.`is_detected`는 특정 타입 `T`에 대해 주어진 표현식(예: `T::foobar`와 같은 중첩 타입 존재 여부)이 유효한지를 컴파일 시간에 확인하는 데 사용된다.
다음은 `is_detected`를 사용하여 특정 타입 내부에 `foobar`라는 중첩 타입 정의가 있는지 확인하는 예제이다.
#include
#include
// 검사하려는 표현식을 정의하는 별칭 템플릿
template
using has_typedef_foobar_t = typename T::foobar;
struct foo {
using foobar = float; // 'foo' 구조체는 'foobar'라는 중첩 타입을 가짐
};
int main() {
std::cout << std::boolalpha;
// std::is_detected<표현식, 타입>::value 형태로 사용
// int 타입에는 foobar 중첩 타입이 없으므로 false 출력
std::cout << std::is_detected
// foo 타입에는 foobar 중첩 타입이 있으므로 true 출력
std::cout << std::is_detected
return 0;
}
이 코드는 C++11의 `void_t`를 사용하는 방식보다 훨씬 간결하며, 타입 특성을 확인하려는 의도를 명확하게 드러낸다. `std::is_detected`는 템플릿 메타프로그래밍 코드를 작성할 때 발생하는 복잡성을 줄여주고 가독성을 높이는 데 도움을 준다.
4. 응용
SFINAE는 함수 오버로딩 과정에서 발생하는 특별한 규칙을 가리키는 용어이다.[5] 템플릿 함수의 후보를 결정할 때, 특정 템플릿 인수로 인해 함수 시그니처 생성(치환)에 실패하더라도 컴파일 오류로 이어지지 않고 단순히 해당 함수를 후보에서 제외하는 것을 의미한다.
원래 SFINAE는 관련 없는 템플릿 선언이 의도치 않게 코드에 포함되었을 때 발생할 수 있는 문제를 방지하기 위해 도입되었다. 하지만 개발자들은 이 규칙을 이용하여 컴파일 시간에 코드의 속성을 확인하는 인트로스펙션 기법으로 활용할 수 있음을 발견했다. 예를 들어, 특정 타입 내부에 원하는 멤버 변수나 타입 정의(`typedef` 또는 `using`)가 존재하는지 등을 컴파일 단계에서 알아낼 수 있다.
이러한 컴파일 타임 인트로스펙션 기능은 템플릿 메타프로그래밍에서 유용하게 사용되며, 조건부 컴파일이나 타입 특성(type traits) 구현의 기반이 된다. 대표적으로 Boost 라이브러리의 `boost::enable_if`[7]와 같은 기능들이 SFINAE 원리를 이용하여 구현되었다. C++11 이후 표준 라이브러리에서도 SFINAE를 활용한 다양한 타입 특성 유틸리티들이 추가되어, 개발자들이 더 간편하게 관련 기능을 사용할 수 있게 되었다.
4. 1. 컴파일 타임 인트로스펙션
SFINAE는 원래 관련 없는 템플릿 선언이 (예를 들어 헤더 파일 포함을 통해) 보일 때 잘못된 형식의 프로그램이 생성되는 것을 피하기 위해 도입되었다.[5] 그러나 이후 개발자들은 이 동작이 컴파일 시간에 인트로스펙션을 수행하는 데 유용하다는 것을 발견했다. 특히, 템플릿을 인스턴스화할 때 템플릿 인수가 특정 속성(예: 특정 멤버 변수나 타입 정의의 존재 유무)을 가지고 있는지 감지하는 데 활용될 수 있다.예를 들어, SFINAE를 사용하면 주어진 자료형(type)에 특정 `typedef`가 포함되어 있는지 컴파일 시간에 확인할 수 있다. 다음은 그 예시이다.
#include
template
struct has_typedef_foobar {
// 크기가 다른 두 개의 배열 타입을 정의한다.
// sizeof(yes)는 1이고, sizeof(no)는 2이다.
typedef char yes[1];
typedef char no[2];
// T에 foobar라는 typedef가 있으면 이 함수 템플릿이 선택된다.
// typename C::foobar* 부분이 SFINAE의 핵심이다. T::foobar가 유효한 타입이어야 한다.
template
static yes& test(typename C::foobar*);
// 그렇지 않으면 이 함수 템플릿이 선택된다. (가변 인자 함수)
// 가변 인자(...)는 모든 타입의 인자를 받을 수 있으며, 오버로딩 우선순위가 가장 낮다.
template
static no& test(...);
// test
// 크기가 sizeof(yes)와 같으면 T 안에 foobar typedef가 존재한다는 의미이다.
static const bool value = sizeof(test
};
struct foo {
typedef float foobar; // foo 구조체 안에는 foobar typedef가 있다.
};
int main() {
std::cout << std::boolalpha;
// int에는 foobar typedef가 없으므로 SFINAE에 의해 첫 번째 test 함수는 제외되고,
// 두 번째 test 함수가 선택되어 반환 타입은 no&가 된다. 따라서 false 출력.
std::cout << has_typedef_foobar
// foo에는 foobar typedef가 있으므로 첫 번째 test 함수가 선택되어 반환 타입은 yes&가 된다.
// 따라서 true 출력.
std::cout << has_typedef_foobar
return 0;
}
위 코드에서 `has_typedef_foobar
만약 `T::foobar`가 유효한 타입이라면, `test` 함수의 첫 번째 오버로딩 버전(반환 타입 `yes&`)이 인스턴스화될 수 있다. `typename C::foobar*` 부분에서 타입 치환이 성공하기 때문이다.
만약 `T::foobar`가 유효하지 않다면(예: `T`가 `int`인 경우), 첫 번째 `test` 함수 템플릿의 인스턴스화는 실패하지만, SFINAE 규칙 덕분에 컴파일 오류가 발생하지 않고 해당 함수는 오버로딩 후보 집합에서 조용히 제외된다. 그러면 두 번째 `test` 함수(반환 타입 `no&`)가 유일한 후보로 남게 되어 선택된다.
최종적으로 `sizeof(test
C++11 표준에서는 타입 특성(type traits)과 `decltype`, 별칭 템플릿(alias template) 등을 이용하여 이 기법을 더 간결하게 구현할 수 있다.
#include
#include
// 어떤 템플릿 인수든 void가 된다.
// 템플릿 인수가 유효한 타입 표현식을 구성하는지 확인하는 데 사용된다.
// (C++17부터 std::void_t로 표준 라이브러리에 포함됨)
template
using void_t = void;
// 기본 템플릿: T::foobar가 없거나 유효하지 않으면 이 템플릿이 선택됨.
// 기본적으로 false_type을 상속받아 value가 false가 된다.
template
struct has_typedef_foobar : std::false_type {};
// 부분 특수화: T::foobar가 유효한 타입이면 void_t
// 이 특수화 버전이 기본 템플릿보다 우선적으로 선택됨.
// true_type을 상속받아 value가 true가 된다.
template
struct has_typedef_foobar
struct foo {
using foobar = float; // C++11의 using 문법으로 typedef와 유사하게 사용
};
int main() {
std::cout << std::boolalpha;
std::cout << has_typedef_foobar
std::cout << has_typedef_foobar
return 0;
}
C++17에서는 이 기법이 표준 라이브러리에서 `std::is_detected` 와 같은 형태로 지원되어 더욱 간결하게 표현할 수 있게 되었다.
#include
#include
// T::foobar 타입 표현이 유효한지 확인하는 헬퍼 타입 별칭
template
using foobar_t = typename T::foobar; // C++11 using 문법
struct foo {
using foobar = float;
};
int main() {
std::cout << std::boolalpha;
// std::is_detected (또는 유사한 메커니즘)를 사용하여 int::foobar 유효성 검사 -> false
std::cout << std::is_detected
// std::is_detected (또는 유사한 메커니즘)를 사용하여 foo::foobar 유효성 검사 -> true
std::cout << std::is_detected
return 0;
}
Boost 라이브러리의 `boost::enable_if`[7] 와 같은 조건부 컴파일 및 타입 특성 관련 기능들도 내부적으로 SFINAE 원리를 적극적으로 활용하여 구현되어 있다.
4. 2. Boost 라이브러리에서의 활용
부스트 라이브러리에서는boost::enable_if
[7] 등을 SFINAE를 사용하여 구현하고 있다.참조
[1]
서적
C++ Templates: The Complete Guide
Addison-Wesley Professional
[2]
간행물
ISO/IEC 14882:2003, Programming languages – C++
International Organization for Standardization
[3]
웹사이트
Boost Enable If
http://www.boost.org[...]
[4]
웹사이트
任意の式によるSFINAE
https://cpprefjp.git[...]
2017-02-01
[5]
서적
C++ Templates: The Complete Guide
Addison-Wesley Professional
[6]
간행물
ISO/IEC 14882:2003, Programming languages — C++
International Organization for Standardization
[7]
웹사이트
Boost Enable If
http://www.boost.org[...]
[8]
서적
C++ Templates: The Complete Guide
https://archive.org/[...]
Addison-Wesley Professional
[9]
간행물
ISO/IEC 14882:2003, Programming languages – C++
International Organization for Standardization
[10]
웹사이트
Boost Enable If
http://www.boost.org[...]
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com