2013-09-07 3 views
3

가변 인수 템플릿 함수의 인수를 모두 같은 형식이어야하도록 어떻게 제한합니까?인수가 같은 Variadic 템플릿 함수 모두 같은 형식

난 복귀 형으로 auto ref를 사용 -1- 값을 전달할 수

CommonType!T either(T...)(T a) if (a.length >= 1) 
{ 
    static if (T.length == 1) 
     return a[0]; 
    else 
     return a[0] ? a[0] : either(a[1 .. $]); 
} 

의 전문이 필요하다. 만족하여야 방법

auto ref either(T... 

따라 무언가

unittest { 
    int x = 1, y = 2; 
    either(x, y) = 3; 
    assert(x == 3); 
} 

이 값 Lisps의 and()or()과 유사한 전에 논리 (도시 생략)과 eitherevery 통해 전달 될 수있다.

이렇게하면 D에서 선호하는 기능 구성을 훨씬 더 강력하게 사용할 수 있습니다.

업데이트

나는 같은 작업 솔루션을 발견했습니다 믿습니다

/** Returns: true if all types T are the same. */ 
template allSame(T...) { 
    static if (T.length <= 1) { 
     enum bool allSame = true; 
    } else { 
     enum bool allSame = is(T[0] == T[1]) && allSame!(T[1..$]); 
    } 
} 

CommonType!T either(T...)(T a) if (a.length >= 1) { 
    static if (T.length == 1) { 
     return a[0]; 
    } else { 
     return a[0] ? a[0] : either(a[1 .. $]); 
    } 
} 
auto ref either(T...)(ref T a) if (a.length >= 1 && allSame!T) { 
    static if (T.length == 1) { 
     return a[0]; 
    } else { 
     return a[0] ? a[0] : either(a[1 .. $]); 
    } 
} 

alias either or; 

그러나 either의 두 가지 버전의 몸은 동일합니다. 이것은 불필요하게 보인다. 이 이중화를 제거하는 가장 좋은 방법은 mixin입니까?

답변

3

당신이 결정하는 템플릿을 작성해야 타입 튜플의 모든 유형이 동일한 경우 :

template allSame(T...) 
{ 
    static if (T.length <= 1) 
     enum bool allSame = true; 
    else 
     enum bool allSame = is(T[0] == T[1]) && allSame!(T[1..$]); 
} 

그럼 그냥 템플릿 제약 조건으로 사용할 :

CommonType!T either(T...)(T a) if (a.length >= 1 && allSame!T) 
+1

목 엑스! BTW : Phobos에서 왜 그렇게 기본적인 것은 아닙니까? –

+1

나는 놀랐다. Phobos는 유형 튜플에 많은 기능을 가지고 있지만 그 중 하나는 가지고 있지 않습니다. –

+0

위의 좋은 해결책을 발견했다고 생각합니다. –

3

과 관련하여 당신의 allSame 템플릿에, 당신은 또한 std.typetuple에서 allSatisfy를 사용할 수 있습니다

import std.typetuple; 

/** Returns: true if all types T are the same. */ 
template allSame(T...) { 

    template isType(X) { enum bool isType = is(X == T[0]); } 
    enum bool allSame = allSatisfy!(isType, T); 
} 

void main() 
{ 
    static assert(!allSame!(int, float, string)); 
    static assert(allSame!(int, int, int)); 
    static assert(allSame!(int)); 
} 
+1

또한'(NoDuplicates! T) .length == 1'을 할 수 있습니다. 자체 문서화가 아닙니다. :) –

+0

멋지 네요! 3 개의 더 많은 문자 (내가 SO 규칙에서 시작하게하지 마라.) –