사용자 정의 리터럴은 C ++에 어떤 새로운 기능을 추가합니까?


139

C ++ 11 개 를 소개 사용자 정의 리터럴 기존 리터럴을 기반으로 새로운 리터럴 구문의 도입을 허용 할 것이다 ( int, hex, string, float) 그래서 어떤 종류의 문자 그대로의 프리젠 테이션을 할 수있을 것입니다.

예 :

// imaginary numbers
std::complex<long double> operator "" _i(long double d) // cooked form
{ 
    return std::complex<long double>(0, d); 
}
auto val = 3.14_i; // val = complex<long double>(0, 3.14)

// binary values
int operator "" _B(const char*); // raw form
int answer = 101010_B; // answer = 42

// std::string
std::string operator "" _s(const char* str, size_t /*length*/) 
{ 
    return std::string(str); 
}

auto hi = "hello"_s + " world"; // + works, "hello"_s is a string not a pointer

// units
assert(1_kg == 2.2_lb); // give or take 0.00462262 pounds

언뜻보기에는 매우 멋지지만 접미사를 생각 _AD하고 _BC날짜를 만들 려고 할 때 연산자 순서로 인해 문제가 있음을 알았을 때 실제로 적용 가능한 방법이 궁금합니다 . 1974/01/06_AD먼저 1974/01(평범하게 int) 평가 하고 나중에 06_AD(8 월과 9 월없이 08 진수 이유로 작성하지 않아도 됨 ). 이것은 1974-1/6_AD연산자 평가 순서가 작동하도록하는 구문을 갖도록함으로써 해결 될 수 있지만 복잡합니다.

그래서 내 질문이 요약 된 것은 이것입니다.이 기능이 스스로를 정당화 할 것이라고 생각하십니까? C ++ 코드를 더 읽기 쉽게 만드는 다른 리터럴은 무엇입니까?


2011 년 6 월 최종 초안에 맞게 구문이 업데이트되었습니다.


8
이걸 끝내기 위해 투표하겠습니다. 제목은 분명히 명백하다.
강아지

76
@DeadMG, 제목에 문제가 있으면 편집 할 수 있습니다. 11 개의 upvotes와 8 개의 즐겨 찾기가있는 3 살짜리 질문을 닫으려고하는 것은 약간 재미 있습니다. (이 사이트의 에티켓이 지난 3 년 동안 바뀌 었다는 언급은 없습니다).
Motti

5
예제에 오류가 있다고 생각합니다 . string operator "" _s(const char*s);"구문 분석하는 데 사용할 수 없습니다 "hello"_s". 이것은 문자열 리터럴이며 추가 size_t매개 변수가 있는 연산자를 찾습니다 . 내가 맞아?
towi

1
내가 궁금했던 것 중 하나는 C ++에서 "휴대용 C"를 작성하는 것이 의미가 있는지 uint16_t, 동작이 구현에 의존하고, 비슷한 유형 uwrap16으로 unum16, 동작이 구현에 독립적 인 uwrap16 w=1; unum16 n=1;w-2n-2수득 것 (uwrap16)65535(int)-1각각 [ uint16_t시스템에서 첫 번째 결과 수득 할 int16 비트를, 그리고 시스템의 제 어디 int크다]. 내가 본 가장 큰 문제는 숫자 리터럴을 처리하는 것이 었습니다.
supercat

1
숫자 리터럴을 다른 정의 된 동작 숫자 형식과 원활하게 상호 운용 할 수 있다면 구현 종속 작업을 수행하려는 코드가 구현에 의존하지 않고도 수행 할 수있는 언어를 만드는 데 이러한 형식을 사용할 수 있어야합니다. 정의 된 행동. 포인터 차이 및 sizeof구현 종속 정수 유형 과 같은 것들이 IDB를 피할 수없는 곳이 몇 군데 있지만 상황은 여전히 ​​상황보다 훨씬 나아질 수 있습니다. 그 개념에 대해 어떻게 생각하십니까?
supercat

답변:


71

생성자 호출 대신 사용자 정의 리터럴을 사용하는 것이 유리한 경우가 있습니다.

#include <bitset>
#include <iostream>

template<char... Bits>
  struct checkbits
  {
    static const bool valid = false;
  };

template<char High, char... Bits>
  struct checkbits<High, Bits...>
  {
    static const bool valid = (High == '0' || High == '1')
                   && checkbits<Bits...>::valid;
  };

template<char High>
  struct checkbits<High>
  {
    static const bool valid = (High == '0' || High == '1');
  };

template<char... Bits>
  inline constexpr std::bitset<sizeof...(Bits)>
  operator"" _bits() noexcept
  {
    static_assert(checkbits<Bits...>::valid, "invalid digit in binary string");
    return std::bitset<sizeof...(Bits)>((char []){Bits..., '\0'});
  }

int
main()
{
  auto bits = 0101010101010101010101010101010101010101010101010101010101010101_bits;
  std::cout << bits << std::endl;
  std::cout << "size = " << bits.size() << std::endl;
  std::cout << "count = " << bits.count() << std::endl;
  std::cout << "value = " << bits.to_ullong() << std::endl;

  //  This triggers the static_assert at compile time.
  auto badbits = 2101010101010101010101010101010101010101010101010101010101010101_bits;

  //  This throws at run time.
  std::bitset<64> badbits2("2101010101010101010101010101010101010101010101010101010101010101_bits");
}

장점은 런타임 예외가 컴파일 타임 오류로 변환된다는 것입니다. 문자열을 가져 오는 비트 셋 ctor에 정적 어설 션을 추가 할 수 없습니다 (적어도 문자열 템플릿 인수가없는 경우).


7
std :: bitset에 적절한 constexpr 생성자를 제공하여 동일한 작업을 수행 할 수 있습니다.
Nicol Bolas

1
@NicolBolas 당신이 맞아요. 나는 실제로 하나가 없다는 것에 놀랐습니다. 너무 늦지 않으면 2014 년에 한두 가지를 제안해야 할 수도 있습니다.
emsr

192

첫눈에 간단한 구문 설탕 인 것 같습니다.

그러나 더 깊게 살펴보면 C ++ 사용자 옵션을 확장하여 고유 한 내장 유형과 똑같이 동작하는 사용자 정의 유형을 생성 하므로 구문 설탕 이상의 의미 가 있습니다.이 작은 "보너스"는 C ++에 대한 흥미로운 C ++ 11 추가입니다.

C ++로 정말로 필요합니까?

지난 몇 년 동안 작성한 코드에서 몇 가지 용도를 보았지만 C ++에서 사용하지 않았다고해서 다른 C ++ 개발자 에게는 흥미롭지 않다는 의미는 아닙니다. .

우리는 컴파일러 정의 리터럴 인 C ++ (및 C)에서 정수를 짧은 정수 또는 긴 정수로, 실수를 부동 또는 더블 (또는 긴 더블)로, 그리고 문자열을 보통 또는 넓은 문자로 입력했습니다. .

C ++에서는 오버 헤드 (인라인 등)없이 자체 유형 (예 : 클래스) 을 만들 수있었습니다 . 우리는 연산자를 유형에 추가하고 유사한 내장 유형처럼 작동하도록 할 수 있었으므로 C ++ 개발자는 언어 자체에 행렬과 복잡한 숫자를 추가했을 때와 마찬가지로 자연스럽게 사용할 수 있습니다. 심지어 캐스트 연산자를 추가 할 수도 있습니다 (보통 나쁜 생각이지만 때로는 올바른 솔루션입니다).

우리는 여전히 사용자 유형이 내장 유형으로 동작하도록하는 한 가지를 놓쳤다 : 사용자 정의 리터럴.

따라서 저는 언어가 자연스럽게 진화 한 것 같지만 가능한 한 완전해야한다고 생각합니다. " 유형을 만들고 내장 유형만큼 가능한 한 동작하려면 여기 도구가 있습니다. .. "

부울, 정수 등 모든 프리미티브를 구조체로 만들고 모든 구조체가 Object에서 파생되도록하는 것이 .NET의 결정과 매우 유사하다고 생각합니다. 이 결정만으로도 Java가 사양에 추가 할 boxing / unboxing 해킹의 양에 관계없이 .NET은 프리미티브로 작업 할 때 Java의 범위를 훨씬 뛰어 넘습니다.

C ++로 정말로 필요합니까?

이 질문은 당신 이 대답 하기위한 것입니다. Bjarne Stroustrup이 아닙니다. 허브 셔터가 아닙니다. C ++ 표준위원회의 멤버는 아닙니다. 이것이 C ++에서 선택하는 이유 이며 유용한 표기법을 내장 유형으로 제한하지 않습니다.

경우 당신이 그것을 필요, 그것은 환영의 추가이다. 경우 당신이 하지, 음 ... 그것을 사용하지 마십시오. 비용이 들지 않습니다.

기능이 선택적인 언어 인 C ++에 오신 것을 환영합니다.

부푼??? 당신의 단지를 보여줘!

부풀어 오른 것과 복잡 한 것 (pun 의도 된 것)에는 차이가 있습니다.

Niels 가 사용자 정의 리터럴을 C ++에 추가하는 새로운 기능은 무엇입니까? 복잡한 숫자를 쓸 수 있다는 것은 C와 C ++에 "최근"추가 된 두 가지 기능 중 하나입니다.

// C89:
MyComplex z1 = { 1, 2 } ;

// C99: You'll note I is a macro, which can lead
// to very interesting situations...
double complex z1 = 1 + 2*I;

// C++:
std::complex<double> z1(1, 2) ;

// C++11: You'll note that "i" won't ever bother
// you elsewhere
std::complex<double> z1 = 1 + 2_i ;

이제 C99 "이중 복소수"유형과 C ++ "std :: complex"유형은 연산자 오버로딩을 사용하여 곱셈, 덧셈, 뺄셈 등을 수행 할 수 있습니다.

그러나 C99에서는 내장 유형과 내장 연산자 오버로드 지원으로 다른 유형을 추가했습니다. 그리고 또 다른 내장 리터럴 기능을 추가했습니다.

C ++에서는 방금 언어의 기존 기능을 사용했으며 문자 기능이 자연스럽게 언어의 진화라는 것을 알았으므로 추가했습니다.

C에서 다른 유형에 대해 동일한 표기법 향상이 필요한 경우, 로비에서 양자 파 기능 (또는 3D 포인트 또는 작업 분야에서 사용하는 기본 유형)을 추가하기 위해 로비까지 불운합니다. 빌트인 타입으로서의 C 규격이 성공.

C ++ 11에서는 직접 할 수 있습니다.

Point p = 25_x + 13_y + 3_z ; // 3D point

부 풀었습니까? 아니오 , C와 C ++ 단지가 리터럴 복잡한 값을 표현하는 방법이 어떻게 필요한지 보여 주듯이 필요가 있습니다.

잘못 설계 되었습니까? 아니요 , 확장 성을 염두에두고 다른 모든 C ++ 기능으로 설계되었습니다.

표기법만을위한 것입니까? 아니요 , 코드에 유형 안전을 추가 할 수도 있습니다.

예를 들어 CSS 지향 코드를 상상해 봅시다.

css::Font::Size p0 = 12_pt ;       // Ok
css::Font::Size p1 = 50_percent ;  // Ok
css::Font::Size p2 = 15_px ;       // Ok
css::Font::Size p3 = 10_em ;       // Ok
css::Font::Size p4 = 15 ;         // ERROR : Won't compile !

그러면 값 할당에 강력한 타이핑을 적용하는 것이 매우 쉽습니다.

위험합니까?

좋은 질문. 이러한 함수는 네임 스페이스가 될 수 있습니까? 그렇다면 잭팟!

어쨌든 도구를 잘못 사용하면 모든 것과 마찬가지로 스스로를 죽일 수 있습니다 . C는 강력하며 C 건을 잘못 사용하면 머리를 쏠 수 있습니다. C ++에는 C 건이 있지만 메스, 테이 저 및 툴킷에서 찾을 수있는 다른 도구도 있습니다. 메스를 오용하고 피를 흘릴 수 있습니다. 또는 매우 우아하고 강력한 코드를 작성할 수 있습니다.

따라서 모든 C ++ 기능과 마찬가지로 실제로 필요합니까? C ++에서 사용하기 전에 대답해야하는 질문입니다. 그렇지 않으면 비용이 들지 않습니다. 그러나 당신이 정말로 필요하다면 적어도 언어는 실망시키지 않을 것입니다.

날짜 예?

당신의 오류는, 당신이 연산자를 혼합하고 있다는 것입니다.

1974/01/06AD
    ^  ^  ^

/ 연산자이기 때문에 컴파일러는 해석해야하므로 피할 수 없습니다. 그리고 AFAIK, 그것은 좋은 것입니다.

문제에 대한 해결책을 찾기 위해 다른 방법으로 리터럴을 작성합니다. 예를 들면 다음과 같습니다.

"1974-01-06"_AD ;   // ISO-like notation
"06/01/1974"_AD ;   // french-date-like notation
"jan 06 1974"_AD ;  // US-date-like notation
19740106_AD ;       // integer-date-like notation

개인적으로 정수와 ISO 날짜를 선택하지만 필요에 따라 다릅니다. 이것은 사용자가 자신의 리터럴 이름을 정의하게하는 요점입니다.


1
감사합니다. 나와 다른 대체 인물이 발견되었습니다. 더 진지하게, 나는 이것을 혼자서 썼지 만 아마도 모국어 표현을 사용하고 있으며 영어로 잘 번역하지 못합니다.
paercebal

제목으로 표시되는 "다른 부분"에 대해서는 미안하지만, 이것은 꽤 긴 게시물을 구성한다고 생각합니다. 굵은 글씨는 단락의 요약입니다. 정당화없이 정보 만 원하는 사람은 제목과 굵은 글씨에 대한 읽기를 제한 할 수 있습니다.
paercebal

3
+1. 정말 좋은 설명입니다. 우리는 이것이 구현되기를 기다리고 있습니다. 우리에게 정말 중요합니다. 우리는 MDE (Model-Driven Engineering)에서 일하며 이것이 필요하다는 것을 알게됩니다. 우리의 경우를 설명하기 위해 아래에 응답을 추가하고 있습니다.
Diego Sevilla

9
@TGV : you can write 1+2i, but you still can't write a+bi, so there's absolutely no point: a+bi예제를 무시해 도 우스운 일이지만, "저주파"라고 인식한다고해서 모든 사람이 그런 것은 아닙니다. . . 큰 그림을 보면 요점은 사용자 정의 객체가 내장 유형과 마찬가지로 언어의 일급 시민으로 간주 될 수 있는지 확인하는 것입니다. 당신이 쓸 수있는 경우에 따라서, 1.5f그리고 1000UL왜 당신은 쓸 수 없습니다 25i심지어 나 100101b? C 및 Java와 달리 사용자 유형은 C ++에서 언어의 2 급 시민으로 간주되지 않습니다.
paercebal

3
@Anton : Most of data still comes from IO: 코드에는 하드 코딩 된 값이 많이 있습니다. 모든 부울에서 봐, 모든 정수는 쓰기 더 편리하기 때문에, 코드에서 오는 모든 복식 x = 2 * y ;대신 x = Two * y여기서 TwoA는 강력한 형식의 정수입니다. 사용자 정의 리터럴을 사용하면 유형을 입력하고 다음을 작성할 수 x = 2_speed * y ;있습니다. 컴파일러에게 계산이 적합한 지 확인하도록합니다. . . 그것은 모두 강력한 타이핑에 관한 것입니다. . . 아마도 당신은 그것을 사용하지 않을 것입니다. 그러나 직장에서 C ++ 11 지원 컴파일러를 사용할 수있게 되 자마자 확실합니다.
paercebal

36

수학 코드에 매우 좋습니다. 내 마음에서 나는 다음 연산자에 대한 사용법을 볼 수 있습니다.

도 정도입니다. 따라서 절대 각도를 훨씬 직관적으로 작성할 수 있습니다.

double operator ""_deg(long double d)
{ 
    // returns radians
    return d*M_PI/180; 
}

또한 다양한 고정 소수점 표현 (DSP 및 그래픽 분야에서 여전히 사용중인)에 사용할 수 있습니다.

int operator ""_fix(long double d)
{ 
    // returns d as a 1.15.16 fixed point number
    return (int)(d*65536.0f); 
}

이것들은 그것을 사용하는 좋은 예처럼 보입니다. 코드의 상수를 더 읽기 쉽게 만듭니다. 코드를 읽을 수 없게 만드는 또 다른 도구이지만 이미 많은 도구 남용으로 인해 많은 피해를 입지 않습니다.


1
"그러나 우리는 이미 너무 많은 도구 남용을 가지고 있기 때문에 더 많은 것을 아프게하지는 않습니다. "최근 c ++ [x] 1234567890 기능이 뒤섞여 있다는 철학이 아니길 바랍니다. 이들 모두를 사용하는 라이브러리와 구성을위한 10 가지 파일 형식 및 코드의 사전 및 사후 처리를위한 2 가지 도구를 사용하는 라이브러리를 배워야한다고 상상해보십시오.
masterxilo

@masterxilo 물론, 실제로, 당신의 예는 터무니 없습니다 : UDL은 함수를위한 구문 설탕처럼 함수보다 배우기가 더 이상 어렵지 않습니다. 게다가 좋은 라이브러리는 UX를 개선하는 데 필요한 기능 만 사용합니다. 꼭. 누군가가 읽을 수없는 코드를 생성하기 위해 기능을 과도하게 사용하는 경우 (작업 라인에서 피할 수 없다고 가정하면 ...) 해당 기능을 잘못 사용하지 않고 사용법에 불과합니다. 또한, 한 사람이 읽을 수없는 것은 다른 사람의 빵과 버터입니다. 모든 의견 및 옵션 입니다. 당신이 그들을 좋아하지 않아도 걱정하지 마십시오! 당신은하지 않습니다 사용할 수 있습니다. 다른 사람도 할 수 있습니다 .
underscore_d

17

UDL은 네임 스페이스이며 선언 / 지시문을 사용하여 가져올 수 있지만 명시 적으로 리터럴과 같은 리터럴을 명시 적으로 지정할 수는 없습니다 3.14std::i. 이는 많은 충돌이 발생하지 않음을 의미합니다.

그것들이 실제로 템플릿 (및 constexpr'd) 될 수 있다는 사실은 UDL로 매우 강력한 일을 할 수 있음을 의미합니다. Bigint 작성자는 컴파일 타임에 (constexpr 또는 템플릿을 통해) 계산하여 임의로 큰 상수를 가질 수 있기 때문에 정말 기쁠 것입니다.

나는 우리가 같이 (그것의 모양에서) 표준에 몇 가지 유용한 리터럴 표시되지 않습니다 단지 슬프다 s에 대한 std::stringi허수 단위.

UDL에 의해 절약 될 코딩 시간은 실제로 그렇게 높지는 않지만, 가독성이 크게 증가하고 더 빠른 계산을 위해 더 많은 계산이 컴파일 시간으로 이동 될 수 있습니다.


네임 스페이스에 대한 요점을 정리해 주셔서 감사합니다 ... 궁금합니다.
Nathan Reed

12

약간의 맥락을 추가하겠습니다. 우리의 작업에는 사용자 정의 리터럴이 많이 필요합니다. 우리는 MDE (Model-Driven Engineering)에서 일합니다. C ++에서 모델과 메타 모델을 정의하려고합니다. 실제로 Ecore에서 C ++ ( EMF4CPP) 로의 매핑을 구현했습니다. ) .

모델 요소를 C ++에서 클래스로 정의 할 수있을 때 문제가 발생합니다. 메타 모델 (Ecore)을 인수가있는 템플릿으로 변환하는 접근 방식을 취하고 있습니다. 템플릿의 인수는 유형과 클래스의 구조적 특성입니다. 예를 들어, 두 개의 int 속성을 가진 클래스는 다음과 같습니다.

typedef ::ecore::Class< Attribute<int>, Attribute<int> > MyClass;

그러나 모델 또는 메타 모델의 모든 요소에는 일반적으로 이름이 있습니다. 우리는 다음과 같이 쓰고 싶습니다 :

typedef ::ecore::Class< "MyClass", Attribute< "x", int>, Attribute<"y", int> > MyClass;

그러나 문자열은 템플릿에 대한 인수로 금지되어 있기 때문에 BUT, C ++ 또는 C ++ 0x에서는이를 허용하지 않습니다. char로 이름을 쓸 수는 있지만 이것은 엉망입니다. 적절한 사용자 정의 리터럴을 사용하면 비슷한 것을 작성할 수 있습니다. 모델 요소 이름을 식별하기 위해 "_n"을 사용한다고 가정 해 봅시다 (정확한 구문을 사용하지 않고 아이디어를 만들기 위해).

typedef ::ecore::Class< MyClass_n, Attribute< x_n, int>, Attribute<y_n, int> > MyClass;

마지막으로 이러한 정의를 템플릿으로 사용하면 형식 정보, 식별, 변환 등이 컴파일 타임에 컴파일러에 의해 결정되므로 실제로 효율적인 모델 요소, 모델 변환 등을 탐색하기위한 알고리즘을 디자인하는 데 많은 도움이됩니다.


4
내가 좋아하는 아주 아주 많이by the compiler at compile time 부분 ... :-)
paercebal

12

Bjarne Stroustrup은이 C ++ 11 talk 에서 UDL에 대해 이야기 합니다 (타입이 풍부한 인터페이스의 첫 번째 섹션에서 약 20 분).

UDL에 대한 그의 기본 논증은 실로주의 형식을 취합니다.

  1. "기본"유형, 즉 내장 기본 유형은 사소한 유형 오류 만 포착 할 수 있습니다. 더 풍부한 유형의 인터페이스를 통해 유형 시스템은 더 많은 종류의 오류를 포착 할 수 있습니다.

  2. 풍부한 유형의 코드가 포착 할 수있는 유형 오류는 실제 코드에 영향을 미칩니다. (그는 중요한 상수의 치수 오류로 인해 악명 높은 실패 인 화성 기후 궤도의 예를 제시합니다.)

  3. 실제 코드에서는 단위가 거의 사용되지 않습니다. 리치 유형을 작성하기 위해 런타임 계산 또는 메모리 오버 헤드가 발생하면 비용이 너무 많이 들고 기존 C ++ 템플릿 단위 코드를 사용하는 것이 표기법에 어긋나므로 아무도 사용하지 않기 때문에 사람들은이를 사용하지 않습니다. (도서관이 10 년 동안 있었지만 경험적으로는 아무도 사용하지 않습니다).

  4. 따라서 엔지니어가 실제 코드에서 단위를 사용하게하려면 (1) 런타임 오버 헤드가없고 (2) 표기법으로 허용되는 장치가 필요했습니다.


9

컴파일 타임 차원 검사를 지원하는 것이 유일한 정당화입니다.

auto force = 2_N; 
auto dx = 2_m; 
auto energy = force * dx; 

assert(energy == 4_J); 

컴파일 타임 차원 분석 및 단위 / 수량 조작 및 변환을위한 작은 C ++ 11, C ++ 14 헤더 전용 라이브러리 인 PhysUnits-CT-Cpp11을 참조하십시오 . 보다 간단 Boost.Units ,지지 않는 부 기호 등 m, g, S 등 리터럴 메트릭 프리픽스 만 표준 C ++ 라이브러리 치수, SI 만, 승수에 따라, 예컨대 m, K, M 등을.


또는 Nic Holthaus의 종속성없이 c ++ 14에 빌드 된 컴파일 타임, 헤더 전용 차원 분석 및 단위 변환 라이브러리 인 units를 참조하십시오 .
Martin Moene

6

흠 ... 아직이 기능에 대해 생각하지 않았습니다. 당신의 샘플은 잘 생각되었고 확실히 흥미 롭습니다. C ++은 현재와 같이 매우 강력하지만 불행히도 읽은 코드에 사용 된 구문은 때때로 너무 복잡합니다. 가독성은 전부는 아니지만 적어도 많은 것입니다. 그리고 이러한 기능은 더 가독성을 높이기 위해 고안되었습니다. 마지막 예를 들어 보면

assert(1_kg == 2.2_lb); // give or take 0.00462262 pounds

... 오늘 어떻게 표현 할까 궁금합니다. KG와 LB 클래스가 있고 암시 적 객체를 비교합니다.

assert(KG(1.0f) == LB(2.2f));

그리고 그렇게 할 것입니다. 더 긴 이름이나 유형을 가진 유형을 사용하여 어댑터를 작성하는 데 유용한 생성자를 갖기를 희망하지 않는 경우, 즉석 암시 적 객체 생성 및 초기화에 추가 될 수 있습니다. 반면에 이미 메소드를 사용하여 오브젝트를 작성하고 초기화 할 수도 있습니다.

그러나 나는 수학에 관한 Nils에 동의합니다. 예를 들어 C 및 C ++ 삼각법 함수는 라디안 입력이 필요합니다. 나는 학위로 생각하기 때문에 Nils와 같은 매우 짧은 암시 적 변환은 매우 훌륭합니다.

궁극적으로 그것은 구문 설탕이 될 것이지만 가독성에 약간의 영향을 미칩니다. 그리고 아마도 일부 표현을 작성하는 것이 더 쉬울 것입니다 (sin (180.0deg)는 sin (deg (180.0))보다 작성하기가 더 쉽습니다. 그런 다음 개념을 남용하는 사람들이있을 것입니다. C ++처럼 표현적인 것이 아니라 매우 제한적인 언어.

아, 내 게시물은 기본적으로 아무것도 말하지 않습니다. 괜찮을 것입니다. 영향은 너무 크지 않습니다. 걱정하지 마십시오. :-)


5
괄호가 불균형입니다! 죄송합니다. 내 OCD도 저를 싫어합니다.
X-Istence

3

나는이 기능을 필요로하지 않았거나 원하지 않았다. 그러나 이것은 Blub 효과 일 수있다 . 내 무릎 저크 반응은 그것이 절름발이이며 원격으로 추가로 해석 될 수있는 모든 작업에 대해 운영자 +에게 과부하가 걸린다고 생각하는 동일한 사람들에게 호소 할 가능성이 있습니다.


나는 확인한다 : 매우 흥미로운 기사.
paercebal

2

C ++은 일반적으로 사용되는 구문에 대해 매우 엄격합니다. 전처리기를 제외하면 사용자 정의 구문 / 문법을 정의하는 데 사용할 수있는 것이 많지 않습니다. 예를 들어 기존 오페라에 과부하를 가할 수는 있지만 새로운 것을 정의 할 수는 없습니다. IMO는 C ++의 정신과 매우 흡사합니다.

좀 더 맞춤형 소스 코드를 만드는 방법은 마음에 들지 않지만 선택한 요점은 나에게 매우 고립되어있어 가장 혼란 스럽습니다.

의도 된 용도로도 소스 코드를 읽기가 훨씬 어려워 질 수 있습니다. 단일 문자는 컨텍스트에서 식별 할 수없는 광범위한 부작용을 가질 수 있습니다. u, l 및 f에 대칭으로 대부분의 개발자는 단일 문자를 선택합니다.

이것은 또한 스코핑을 문제로 바꿀 수 있습니다. 전역 네임 스페이스에서 단일 문자를 사용하는 것은 나쁜 습관으로 간주 될 것입니다. 라이브러리를 더 쉽게 믹싱하는 것으로 생각되는 도구 (네임 스페이스 및 설명 식별자)는 아마도 그 목적을 잃을 것입니다.

부스트 단위 와 같은 단위 라이브러리와 함께 "자동"과 함께 사용하는 장점이 있지만이 adition을 사용하기에는 충분하지 않습니다.

그러나 우리가 어떤 영리한 아이디어를 생각해 낼지 궁금합니다.


1
using single letters in global namespace will probably be considered bad practice그러나 그것은 관련성이 없습니다. 전역 NS는 구현을 위해 예약되어 있습니다. 그것은 UDL이 선천적으로 혼란을 일으킨다는 생각과 적어도 2 가지입니다. 예를 들어 stdlib inline namespace가 사용자가 원하는 경우 도매를 가져올 수 있도록 stdlib가이를 선언하는 이유는 네임 스페이스를 범위 지정해야하는 것입니다 .
underscore_d

2

이진 문자열에 사용자 리터럴을 다음과 같이 사용했습니다.

 "asd\0\0\0\1"_b

문자열을 반으로 자르지 std::string(str, n)않도록 생성자를 사용 \0합니다. (이 프로젝트는 다양한 파일 형식으로 많은 작업을 수행합니다.)

이것은 std::string에 대한 래퍼를 선호하여 도랑 때도 도움이되었습니다 std::vector.


-5

그 라인 노이즈는 엄청납니다. 또한 읽는 것도 끔찍합니다.

그들이 어떤 종류의 예제로 새로운 구문을 추가했는지 추론 했습니까? 예를 들어 이미 C ++ 0x를 사용하는 몇 개의 프로그램이 있습니까?

나를 위해,이 부분은 :

auto val = 3.14_i

이 부분을 정당화하지 않습니다 :

std::complex<double> operator ""_i(long double d) // cooked form
{ 
    return std::complex(0, d);
}

1000 줄에 i 구문을 사용하더라도 마찬가지입니다. 글을 쓰면 아마도 그와 함께 10000 줄의 다른 것을 쓸 것입니다. 특히, 아마도 여전히 대부분 어디에나 쓸 것입니다 :

std::complex<double> val = 3.14i

'auto'-키워드는 아마도 정당화 될 수 있습니다. 그러나이 측면에서 C ++ 0x보다 낫기 때문에 C ++ 만 가져 가십시오.

std::complex<double> val = std::complex(0, 3.14);

마치 .. 그렇게 간단합니다. 모든 std 및 뾰족한 괄호는 어디에서나 사용하면 불충분하다고 생각했습니다. 복잡한 상태에서 std :: complex를 전환하기 위해 C ++ 0x에 어떤 구문이 있는지 추측하기 시작하지 않습니다.

complex = std::complex<double>;

아마도 간단하지만 C ++ 0x에서 그렇게 간단하지는 않습니다.

typedef std::complex<double> complex;

complex val = std::complex(0, 3.14);

혹시? > :)

어쨌든 요점은 다음과 같습니다. std :: complex (0, 3.14) 대신 3.14i 쓰기; 몇 가지 특별한 경우를 제외하고는 전체적으로 많은 시간을 절약하지 못합니다.


10
@Cheery : "auto val = 3.14i"는이를 지원하기 위해 작성된 코드를 정당화하지 않습니다. 나는 "printf ("% i ", 25)"는 printf 용으로 작성된 코드를 정당화하지 못한다고 대답 할 수있다. 패턴이 보입니까?
paercebal

5
@Cheery : "저것의 라인 노이즈는 엄청납니다". 아니요, "읽기 끔찍합니다"는 아닙니다. 주관적인 주장은 흥미롭지 만,이 기능에 대한 코드가 놀랍고 충격적인 것과는 거리가 멀다는 것을 알기 위해 연산자 오버로딩을 살펴보아야합니다. C ++ 개발자의 경우
paercebal

3
자동은 가독성에 도움이됩니다. for 루프에서 인터 레이터를 사용하는 것을 고려하십시오. .
KitsuneYMG

1
@kts : C ++ 1x를 사용하면 다음과 같은 람다와 범위를 갖게됩니다.
Joe D

3
C ++ 라인이 C ++ 0x보다 나은 경우 내 라인이 더 좋습니다. 씁니다 : std::complex<double> val(0, 3.14);.
Ben Voigt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.