내 C++ 11 지식은 내가 원하는 것보다 훨씬 제한되어 있으므로 아직 알지 못하는 것을 개선하는 새로운 기능이있을 수 있지만 생각할 수있는 세 가지 영역이 있습니다 템플릿 제약 조건, static if
및 타입 인트로 스펙 (inrospection)과 같은 문제가 있습니다.
D에서 범위 기반 함수는 일반적으로 허용하는 범위 유형 (예 : 전달 범위 대 임의 액세스 범위)을 나타내는 템플릿 제약 조건을 갖습니다. 그것은 유형에 전달되는 것을 확인
auto sort(alias less = "a < b", Range)(Range r)
if(isRandomAccessRange!Range &&
hasSlicing!Range &&
hasLength!Range)
{...}
그것이 슬라이스 할 수있는, 랜덤 액세스 범위이며,이 length
속성이 그 : 예를 들어, 여기 std.algorithm.sort
에 대한 단순화 된 서명입니다. 이러한 요구 사항을 만족시키지 못하는 형식은 sort
으로 컴파일되지 않으며 템플릿 제약 조건이 실패하면 프로그래머가 왜 sort
과 함께 작동하지 않는지 명확히 알 수 있습니다 (중간에서 불쾌한 컴파일러 오류가 발생하는 것보다 주어진 타입으로 컴파일하는데 실패 할 때 템플리트 된 함수의).
sort
이 올바른 연산을 수행 할 수 없기 때문에 sort
이 컴파일에 실패 할 때 컴파일 오류를 제공하는 것보다 유용성이 향상 된 것처럼 보일 수 있지만 사실은 함수 오버로딩과 유형에 큰 영향을줍니다 내성. 예를 들어, 여기 std.algorithm.find
의 과부하 두 같습니다 번째 순방향 범위 바늘을 수용하는 반면
R find(alias pred = "a == b", R, E)(R haystack, E needle)
if(isInputRange!R &&
is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
{...}
R1 find(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if(isForwardRange!R1 && isForwardRange!R2 &&
is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool) &&
!isRandomAccessRange!R1)
{...}
첫번째는, 단일 소자 인 바늘을 수용한다. 이 둘은 완전히 템플릿 제약 조건에 따라 다른 매개 변수 유형을 가질 수 있으며 내부적으로 매우 다른 코드를 가질 수 있습니다. 템플리트 제약 조건과 같은 것이 없으면 인수의 속성에 오버로드 된 템플릿 함수를 사용할 수 없습니다 (특정 유형 자체에 오버로드되는 것과 반대 됨). 따라서 불가능한 경우가 아니라면 서로 다른 구현을 갖는 것이 훨씬 더 어려워집니다. 사용되는 범위 장르 (예 : 입력 범위 대 전진 범위) 또는 사용되는 유형의 기타 속성. 일부 작업은 개념과 유사한 아이디어로 C++에서이 영역에서 수행되었지만 AFAIK, C++은 인수 유형의 속성을 기반으로 템플릿을 오버로드하는 데 필요한 기능이 여전히 부족합니다 (템플릿 함수 또는 템플릿 유형 임). 특정 인수 유형을 전문으로하는 것 (템플릿 전문화에서 발생)
관련 기능은 static if
입니다. if
과 동일하지만, 조건이 컴파일 타임에 계산된다는 점과 true
또는 false
이 실제로 어떤 분기가 실행되는 것과는 대조적으로 어떤 분기가 컴파일되는지를 결정합니다. 컴파일시 알려진 조건에 따라 코드를 분기 할 수 있습니다. 예 : 당신은 본질적으로 하나의 함수 내에서 템플릿 함수의 오버로드를 넣을 수있는 어느 정도
static if(isDynamicArray!T)
{}
else
{}
또는
static if(isRandomAccessRange!Range)
{}
else static if(isBidirectionalRange!Range)
{}
else static if(isForwardRange!Range)
{}
else static if(isInputRange!Range)
{}
else
static assert(0, Range.stringof ~ " is not a valid range!");
static if
캔, 템플릿 제약의 필요성을 미연에 방지. 예 :
R find(alias pred = "a == b", R, E)(R haystack, E needle)
{
static if(isInputRange!R &&
is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
{...}
else static if(isForwardRange!R1 && isForwardRange!R2 &&
is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool) &&
!isRandomAccessRange!R1)
{...}
}
하지만 컴파일이 실패 할 때 여전히 지저분 오류가 발생하고 (적어도 D의 구현) 템플릿을 오버로드 할 수 있도록 템플릿을 인스턴스화되기 전에 과부하가 결정되기 때문에 실제로 그것을한다. 따라서 static if
을 사용하여 템플릿 구현을 전문화 할 수는 있지만 템플릿 제약 조건이 필요없는 템플릿 제약 조건을 충분히 얻을 수는 없습니다.
대신에 static if
은 기능 구현의 일부만 전문화하거나 범위 형식이 래핑 할 범위 형식의 특성을 적절하게 상속 할 수 있도록 만드는 데 적합합니다. 예를 들어 정수 배열에서 std.algorithm.map
을 호출하면 결과 범위는 슬라이싱 (소스 범위가 있기 때문에) 될 수 있지만 슬라이스가없는 범위에서 map
을 호출하면 (예 : std.algorithm.filter
의 범위는 ' 슬라이스가 생겼습니다), 결과 범위는 슬라이싱되지 않습니다. 이를 수행하기 위해 map
은 소스 범위가 지원하는 경우에만 opSlice
에서 static if
을 사용하여 컴파일합니다. 현재의 반환 유형 및 그 코드는 컴파일 여부가 static if
의 결과에 달려 map
'이
static if (hasSlicing!R)
{
static if (is(typeof(_input[ulong.max .. ulong.max])))
private alias opSlice_t = ulong;
else
private alias opSlice_t = uint;
static if (hasLength!R)
{
auto opSlice(opSlice_t low, opSlice_t high)
{
return typeof(this)(_input[low .. high]);
}
}
else static if (is(typeof(_input[opSlice_t.max .. $])))
{
struct DollarToken{}
enum opDollar = DollarToken.init;
auto opSlice(opSlice_t low, DollarToken)
{
return typeof(this)(_input[low .. $]);
}
auto opSlice(opSlice_t low, opSlice_t high)
{
return this[low .. $].take(high - low);
}
}
}
이 map
의 유형 정의의 코드처럼 보이는 수행의 코드' 그 중 어떤 것도 특정 유형을 기반으로하는 템플릿 특수화로 대체 할 수 없으며 그 중 어떤 유형을 사용하든 모든 새 유형 (분명히 수용 할 수 없음)에 대해 map
에 대한 특수화 된 템플릿을 작성할 필요가 없습니다. 특정 유형이 아닌 유형의 속성을 기반으로 코드를 컴파일하려면 static if
과 같은 것이 필요합니다 (현재 C++에는 없습니다).
C++에서 부족한 세 번째 주요 항목은 (내가 전반적으로 더 많이 또는 덜 밟았습니다) 유형 인트로 피싱입니다. is(typeof(binaryFun!pred(haystack.front, needle)) : bool)
또는 isForwardRange!Range
과 같은 것을 할 수 있다는 사실이 중요합니다. 특정 유형에 특정 속성 집합이 있는지 또는 특정 코드가 컴파일되었는지 여부를 확인하지 않으면 템플리트 제약 조건과 static if
이 사용하는 조건을 작성할 수 없습니다. 예를 들어, std.range.isInputRange
는
template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r = void; // can define a range object
if (r.empty) {} // can test for empty
r.popFront(); // can invoke popFront()
auto h = r.front; // can get the front of the range
}));
}
그것은 코드의 특정 부분이 주어진 형식에 대해 컴파일합니다 확인이 같이 보입니다. 그럴 경우 해당 유형을 입력 범위로 사용할 수 있습니다. 그렇지 않으면 그럴 수 없습니다. AFAIK, C++에서 이와 같은 것을 막연하게 수행하는 것은 불가능합니다. 하지만 범위를 정교하게 구현하려면 isInputRange
같은 것을하거나 특정 유형이 sort
- is(typeof(sort(myRange)))
으로 컴파일되는지 테스트 할 수 있어야합니다.이를 사용하지 않으면 특정 범위가 지원하는 작업 유형을 기반으로 구현을 전문화 할 수 없으며 범위를 래핑 할 때 범위의 특성을 올바르게 전달할 수 없으며 범위 함수는 모든 인수를 항상 새로운 범위로 래핑합니다. 당신은 제대로 작동하지 않을 타입으로 컴파일되지 않도록 함수를 적절히 보호 할 수 없다. 그리고 물론 static if
의 결과와 템플릿 제약 조건도 형식 인트로피멘트에 영향을 미치기 때문에 (이는 컴파일 대상과 컴파일 대상에 영향을 미치기 때문에) 3 가지 기능이 매우 상호 연결됩니다.
실제로 범위가 C++에서 잘 작동하지 않는 주된 이유는 몇 가지 이유 인 metaprogramming in C++ is primitive in comparison to metaprogramming in D입니다. AFAIK, 이러한 기능 (또는 비슷한 것들)을 C++에 추가하고 문제를 해결할 수있는 이유는 없습니다. 그러나 C++에 D와 비슷한 메타 프로그래밍 기능이 있기 전까지는 C++의 범위가 심각하게 약화 될 것입니다.
mixins 및 Uniform Function Call Syntax와 같은 다른 기능도 도움이되지만 근본적인 곳은 없습니다. Mixins은 주로 코드 중복을 줄이는 데 주로 도움이되며 UFCS는 일 반적인 코드가 모든 함수를 멤버 함수처럼 호출하여 유형이 특정 함수 (예 : find
)를 정의하는 경우 해당 함수를 호출 할 수 있도록합니다. 좀 더 일반적이고 자유로운 함수 버전 대신에 사용됩니다. 그리고 자유 함수가 사용되기 때문에 코드는 그러한 멤버 함수가 선언되지 않으면 여전히 작동합니다. UFCS는 근본적으로 요구되지 않으며, C++ 11이 begin
및 end
으로 수행 한 것과 같이 모든 방향에서 반대 방향으로 자유로운 기능을 선호 할 수도 있습니다. 그렇지만 실제로는 자유 기능이 테스트 할 수 있어야합니다. 멤버 함수가 존재하는지 확인한 다음 자체 구현을 사용하는 대신 내부적으로 멤버 함수를 호출합니다. 따라서 다시 static if
및/또는 템플릿 제약 조건과 함께 인트로 스펙을 입력해야합니다.
범위를 좋아하는만큼이 시점에서 나는 C++에서 그 (것)들로 무엇이든 시도하는 것을 포기했습니다. 왜냐하면 그것들을 정상적으로 만들기위한 기능이 없기 때문입니다. 그러나 다른 사람들이 그것을하는 방법을 알아낼 수 있다면, 그들에게 더 많은 힘이 있습니다. 어쨌든 범위에 관계없이 템플릿 제한, static if
및 유형 내성 검사와 같은 C++ 이득 기능을보고 싶습니다. 메타 프로그래밍이 방법 덜 유쾌하고, 그 동안 D에서 항상 수행합니다. , 나는 C++에서 거의 그것을하지 않는다.
? 최종 반복자는 다른 반복자와 비교할 때 완료 여부를 알려주는 객체입니다. Lazy C++ iterator 기반 범위는 어렵지 않습니다. 공상 상황에서는, 게으른 범위와 같은 몇 가지 추가 보일러가 필요하다 : 간단한 상황, 도시락 연속 메모리를 통해 다양한처럼, 나는 D 스타일의 범위가 빨리 될 수 있습니다 상상할 수 없습니다. – Yakk
부스트 변환 반복기 등을 봤어? 특히, D에서 저렴하지만 C++에서는 비싸고 불가능한 구체적인 문제를 제시하십시오. – Yakk
당신은 그 이유를 믿습니다. 나는 네가 틀렸다고 생각하거나 내가 익숙하지 않은 방식으로 말을 사용한다. 어쨌든, 구체적인 문제는 제발. '의 – Yakk