개요
타입, 객체, 코드 등에 대한 구현/정의 속성을 설명
문법
C++11
C++17
[[ using attribute-namespace : attribute-list ]]
표준 속성
[[noreturn]]
C++11
함수가 return 하지 않음을 지정
함수가 반환되는 경우 동작이 정의되지 않음
함수 선언에서 함수 이름에만 적용 가능
throw 사용하여 함수를 빠져나가야 함
[[carries_dependency]]
C++11
indicates that dependency chain in release-consume std::memory_order propagates in and out of the function
[[deprecated]] / [[deprecated(“reason”)]]
C++14
사용은 허용되지만 권장되지 않음
사용 시 컴파일 경고 발생
class/struct/union
typedef/using
[[deprecated]] typedef C* PC;
using PC [[deprecated]] = C*;
variable
non-static 데이터 멤버
class T { [[deprecated]] int i; };
함수
namespace
namespace [[deprecated]] NS { int i; }
enum
enum [[deprecated]] E {};
enum { A [[deprecated]], B [[deprecated]] = 42 };
템플릿
template <> class [[deprecated]] C<int> {};
[[fallthrough]]
C++17
switch문에서 특정 라벨에 break가 없는게 의도적임을 지정
컴파일 경고가 발생하지 않음
[[nodiscard]] / [[nodiscard(“reason”)]]
[[nodiscard]]
[[nodiscard(“reason”)]]
함수의 반환 값을 사용하지 않으면 컴파일 경고 발생
해당 속성으로 선언된 함수
해당 속성으로 선언된 enum, class 등을 반환하는 함수
[[maybe_unused]]
C++17
사용하지 않는 변수 등에 대한 경고를 억제
[[likely]] / [[unlikely]]
C++20
컴파일러가 적절한 최적화를 하도록 분기문에 실행 빈도를 지정
[[no_unique_address]]
C++20
non-static 데이터 멤버가 다른 non-static 데이터 멤버와 구별되는 주소를 가질 필요가 없음을 지정
[[assume]]
C++23
표현식이 항상 true로 평가되도록 지정
예제
[[noreturn]]
코드
#include <iostream>
using namespace std ;
[[ noreturn ]] void func1 () { throw "throw" ; };
void func2 [[ noreturn ]] () { throw "throw" ; };
int main () {
try {
func1 ();
} catch (...) {
cout << "~~~ func1()" << endl ;
}
try {
func2 ();
} catch (...) {
cout << "~~~ func2()" << endl ;
}
return 0 ;
}
실행 결과
[[deprecated]] / [[deprecated(“reason”)]]
코드
#include <iostream>
#include <string>
using namespace std ;
class [[ deprecated ]] Test1 {
public:
void Print () { cout << "Test1::Print()" << endl ; }
};
class Test2 {
public:
[[ deprecated ]] int i ;
[[ deprecated ]] void Print () { cout << "Test2::Print()" << endl ; }
};
template < typename T > class Test3 {};
template < > class [[ deprecated ]] Test3 < int > {};
[[ deprecated ]] int I = 0 ;
int main () {
cout << I << endl ;
Test1 (). Print ();
Test2 (). i ;
Test2 (). Print ();
[[ deprecated ]] int i = 0 ;
cout << i << endl ;
Test3 < string > ();
Test3 < int > ();
return 0 ;
}
실행 결과
main.cpp: In function ‘int main() ’:
main.cpp:23:17: warning: ‘I’ is deprecated [ -Wdeprecated-declarations ]
23 | cout << I << endl;
| ^
main.cpp:20:20: note: declared here
20 | [[deprecated]] int I = 0;
| ^
main.cpp:25:15: warning: ‘Test1’ is deprecated [-Wdeprecated-declarations]
25 | Test1().Print();
| ^
main.cpp:6:22: note: declared here
6 | class [[deprecated]] Test1 {
| ^~~~~
main.cpp:27:17: warning: ‘Test2::i’ is deprecated [-Wdeprecated-declarations]
27 | Test2().i;
| ^
main.cpp:13:36: note: declared here
13 | [[deprecated]] int i;
| ^
main.cpp:27:17: warning: ‘Test2::i’ is deprecated [-Wdeprecated-declarations]
27 | Test2().i;
| ^
main.cpp:13:36: note: declared here
13 | [[deprecated]] int i;
| ^
main.cpp:27:17: warning: ‘Test2::i’ is deprecated [-Wdeprecated-declarations]
27 | Test2().i;
| ^
main.cpp:13:36: note: declared here
13 | [[deprecated]] int i;
| ^
main.cpp:28:22: warning: ‘void Test2::Print()’ is deprecated [-Wdeprecated-declarations]
28 | Test2().Print();
| ~~~~~~~~~~~~~^~
main.cpp:14:37: note: declared here
14 | [[deprecated]] void Print() { cout << "Test2::Print()" << endl; }
| ^~~~~
main.cpp:31:17: warning: ‘i’ is deprecated [-Wdeprecated-declarations]
31 | cout << i << endl;
| ^
main.cpp:30:28: note: declared here
30 | [[deprecated]] int i = 0;
| ^
main.cpp:34:20: warning: ‘Test3’ is deprecated [-Wdeprecated-declarations]
34 | Test3<int>();
| ^
main.cpp:18:34: note: declared here
18 | template <> class [[deprecated]] Test3<int> {};
| ^~~~~~~~~~
0
Test1::Print()
Test2::Print()
0
[[fallthrough]]
코드
#include <iostream>
using namespace std ;
int main () {
int i = 0 ;
switch ( i ) {
case 0 :
cout << 0 << endl ;
[[ fallthrough ]];
case 1 :
cout << 1 << endl ;
break ;
}
return 0 ;
}
실행 결과
[[nodiscard]] / [[nodiscard(“reason”)]]
코드
class [[ nodiscard ]] Test {};
Test func1 () { return Test (); }
[[ nodiscard ( "reason" )]] int func2 () { return 1 ; };
int main () {
func1 ();
func2 ();
return 0 ;
}
실행 결과
main.cpp: In function ‘int main() ’:
main.cpp:7:14: warning: ignoring returned value of type ‘Test’, declared with attribute ‘nodiscard’ [ -Wunused-result ]
7 | func1() ;
| ~~~~~^~
main.cpp:2:6: note: in call to ‘Test func1() ’, declared here
2 | Test func1() { return Test() ; }
| ^~~~~
main.cpp:1:21: note: ‘Test’ declared here
1 | class [[ nodiscard]] Test {} ;
| ^~~~
main.cpp:9:14: warning: ignoring return value of ‘int func2() ’, declared with attribute ‘nodiscard’: ‘reason’ [ -Wunused-result ]
9 | func2() ;
| ~~~~~^~
main.cpp:4:29: note: declared here
4 | [[ nodiscard( "reason" )]] int func2() { return 1; } ;
| ^~~~~
[[maybe_unused]]
코드
[[ maybe_unused ]] void func ([[ maybe_unused ]] int x , int y ) {}
int main () {
int i = 0 ;
[[ maybe_unused ]] double d = 0.0 ;
return 0 ;
}
실행 결과
main.cpp: In function ‘int main() ’:
main.cpp:4:13: warning: unused variable ‘i’ [ -Wunused-variable ]
4 | int i = 0;
| ^
[[likely]] / [[unlikely]]
코드
#include <algorithm>
#include <chrono>
#include <iostream>
using namespace std ;
constexpr long long fact_with_attributes ( long long n ) noexcept {
if ( n > 1 ) [[ likely ]] {
return n * fact_with_attributes ( n - 1 );
} else [[ unlikely ]] {
return 1 ;
}
}
constexpr long long fact_no_attributes ( long long n ) noexcept {
if ( n > 1 ) {
return n * fact_no_attributes ( n - 1 );
} else {
return 1 ;
}
}
int main () {
auto run = []( auto func ) {
const auto start = chrono :: high_resolution_clock :: now ();
for ( int i = 0 ; i < 2000000 ; i ++ ) {
for ( int j = 0 ; j <= 20 ; j ++ ) {
func ( j );
}
}
const auto end = chrono :: high_resolution_clock :: now ();
const chrono :: duration < double > result = end - start ;
cout << result . count () << endl ;
};
run ( fact_with_attributes );
run ( fact_no_attributes );
return 0 ;
}
실행 결과
[[no_unique_address]]
코드
#include <iostream>
using namespace std ;
class Test {};
class Test1 {
private:
int i ;
Test t ;
public:
void Print () {
cout << & this -> i << endl ;
cout << & this -> t << endl ;
}
};
class Test2 {
private:
int i ;
[[ no_unique_address ]] Test t ;
public:
void Print () {
cout << & this -> i << endl ;
cout << & this -> t << endl ;
}
};
int main () {
cout << sizeof ( int ) << endl ;
cout << sizeof ( Test ) << endl ;
cout << sizeof ( Test1 ) << endl ;
cout << sizeof ( Test2 ) << endl ;
cout << "------" << endl ;
Test1 (). Print ();
cout << "------" << endl ;
Test2 (). Print ();
return 0 ;
}
실행 결과
4
1
8
4
------
0x7ffd4e7a40b4
0x7ffd4e7a40b8
------
0x7ffd4e7a40bc
0x7ffd4e7a40bc
Tags:
assume ,
attribute ,
C++ ,
C++11 ,
C++14 ,
C++17 ,
C++20 ,
C++23 ,
carries_dependency ,
deprecated ,
fallthrough ,
likely ,
maybe_unused ,
no_unique_address ,
nodiscard ,
noreturn ,
programming-language ,
unlikely
Categories:
C++ ,
programming-language
Updated: November 1, 2022