C ++에서 조건부 typedef를 만드는 방법


89

나는 다음과 같은 것을 시도하고 있습니다.

#include <iostream>
#include <random>

typedef int Integer;

#if sizeof(Integer) <= 4
    typedef std::mt19937     Engine;
#else
    typedef std::mt19937_64  Engine;
#endif

int main()
{
    std::cout << sizeof(Integer) << std::endl;
    return 0;
}

하지만이 오류가 발생합니다.

error: missing binary operator before token "("

조건부 typedef를 올바르게 만들려면 어떻게해야합니까?


25
전처리 기는 sizeof, 또는 다른 C ++ 구조에 대해 아무것도 모릅니다 . 그것은 확실히 당신이 직접 만든 것들에 대해 알고하지 않습니다 typedef즉 아직 분석되지 않았기 때문에.
밝기 경주 궤도에

2
당신은 사용할 수 있습니다 enable_if또는 conditional조건부 형식 정의를 정의하는,하지만 당신은 그것에 대해 처리기를 사용할 수 없습니다.
Bartek Banachewicz 2013

1
@LightnessRacesinOrbit : 전처리 및 컴파일이 GCC에 통합되어 있으므로 소프트웨어 처리 코드가 사용자가 만든 유형 정의에 대해 알지 못하지만 GCC의 경우 거짓으로 알려진 것은 확실하지 않습니다. sizeof전 처리기 조건에서 작동 할 수없는 이유 는 구현이 작동하는 방식 때문이 아니라 언어가 그렇게 정의 되었기 때문입니다.
Eric Postpischil 2013-08-28

1
@LightnessRacesinOrbit : 번역 단계는 처리 순서가 아니라 구문과 의미를 정의합니다. C ++ 2011 (N3092) 2.2 [lex.phases] 참고 11, "실제로 다른 단계가 함께 접힐 수 있지만 구현은 이러한 개별 단계가 발생하는 것처럼 동작해야합니다." GCC에 대한 내 요점은 이것이 구현이 작동하는 방식이 잘못되었다는 귀하의 주장을 보여주기 때문에 관련이 있습니다. 즉, 귀하의 의견 은 특정 구현 방법이이를 방지 한다고 주장 합니다. 그러나 이것을 막는 것은 구현이 아닙니다 (우리는 수 있습니다). 그것은 언어 정의입니다.
Eric Postpischil 2013-08-28

1
@Eric : 구현에 대해 어떤 것도 주장하려는 것이 아닙니다. 나는 확실히 어떤 특정한 것을 언급하지 않았다. 내 의견은 귀하와 마찬가지로 as-if 규칙이 적용되는 행동을 언급했습니다. 나는 우리가 실제로 여기에서 어떤 것에 대해 동의하지 않는다고 생각하지 않습니다. 당신의 언어 변호사는 거울에서 직접 왔을 수도 있습니다. :)
궤도의

답변:


139

std::conditionalC ++ 11 의 메타 함수를 사용합니다 .

#include <type_traits>  //include this

typedef std::conditional<sizeof(int) <= 4,
                         std::mt19937,
                         std::mt19937_64>::type Engine;

에서 사용하는 유형이 예를 sizeof들어 템플릿 매개 변수 인 T경우 다음 typename과 같이 사용해야 합니다.

typedef typename std::conditional<sizeof(T) <= 4, // T is template parameter
                                  std::mt19937,
                                  std::mt19937_64>::type Engine;

또는 다음과 같이 Engine의존하십시오 T.

template<typename T>
using Engine = typename std::conditional<sizeof(T) <= 4, 
                                         std::mt19937,
                                         std::mt19937_64>::type;

유연한 이제로 사용할 수 있기 때문에, :

Engine<int>  engine1;
Engine<long> engine2;
Engine<T>    engine3; // where T could be template parameter!

4
+1 Minor nitpick : sizeof(int) <= 464 비트 Windows 시스템에서 GCC (MinGW) x64 컴파일러는 sizeof(int) = sizeof(long) = 4. 더 나은 방법은 sizeof(void*) <= 4.
legends2k 2013-07-25

@ legends2k : 의미 Engine<void*> engine4;? ;-)
Nawaz

2
@Nawaz : 물론 아닙니다 :) std::conditional<sizeof(void*) <= 4, std::mt19937, std::mt19937_64>첫 번째 코드 스 니펫에서 의미 했습니다.
legends2k 2013

1
@ legends2k : 내가 당신에게 제공했다면 왜 그것을 사용 Engine<void*>하겠습니까? :피
Nawaz

@Nawaz : 하하 ... 그건 사실입니다. 그러나 OP는 아마도 크기에 따라 아키텍처를 감지하는 함정을 알아야한다고 생각했습니다.int :)
legends2k

35

사용 std::conditional하면 다음과 같이 할 수 있습니다.

using Engine = std::conditional<sizeof(int) <= 4, 
                               std::mt19937, 
                               std::mt19937_64
                               >::type;

를하고 싶다면 그렇게 typedef할 수도 있습니다.

typedef std::conditional<sizeof(int) <= 4, 
                         std::mt19937, 
                         std::mt19937_64
                         >::type Engine

필요가 없습니다 typename여기
gx_

@gx_ 예, 구체적인 유형이 아닌 템플릿으로 작업하면서 거기에 넣곤했습니다.
Rapptz 2013

1
@LightnessRacesinOrbit 글쎄, 나는 그것을 조금 고쳤다.
Rapptz 2013

5

사용할 수있는 C ++ 11이없는 경우 (사용할 계획이라면 사용하는 것처럼 보이지만 std::mt19937) Boost Metaprogramming Library (MPL)를 사용하여 C ++ 11 지원없이 동일한 작업을 구현할 수 있습니다 . 다음은 컴파일 가능한 예입니다.

#include <boost/mpl/if.hpp>
#include <iostream>
#include <typeinfo>

namespace mpl = boost::mpl;

struct foo { };
struct bar { };

int main()
{
    typedef mpl::if_c<sizeof(int) <= 4, foo, bar>::type Engine;

    Engine a;
    std::cout << typeid(a).name() << std::endl;
}

이것은 여기에 4 바이트이므로 foo내 시스템에서 의 망가진 이름을 인쇄합니다 int.


1
if_c대신 사용하지 않는 이유는 무엇 입니까? 작성하고 이해하는 것이 더 쉬울 것 mpl::if_c<sizeof(int)<=4, foo, bar>::type입니다. 그렇지 않나요?
Nawaz 2013

1
@Nawaz : 사실, 여러 가지면에서 더 좋습니다. 나는 잊었다 mpl::if_c. 대신 해당 접근 방식을 사용하도록 예제를 업데이트했습니다.
Jason R
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.