문제

다음과 같이 보이는 템플릿 컨테이너 클래스가 있습니다.

template<
   class KeyType, 
   class ValueType, 
   class KeyCompareFunctor   = AnObnoxiouslyLongSequenceOfCharacters<KeyType>, 
   class ValueCompareFunctor = AnObnoxiouslyLongSequenceOfCharacters<ValueType> 
>
   class MyClass
   {
      [...]
   }

즉,이 수업의 객체를 인스턴스화 할 때 여러 가지 방법을 수행 할 수 있습니다.

MyClass<MyKeyType, MyValueType> myObject;
MyClass<MyKeyType, MyValueType, MyCustomKeyCompareFunctor> myObject;
MyClass<MyKeyType, MyValueType, MyCustomKeyCompareFunctor, MyCustomValueCompareFunctor> myObject;

그것들은 모두 좋습니다. 문제는 ValuecompareFunctor 인수의 비 기본 버전을 사용하는 MyClass를 인스턴스화하고 싶을 때 발생하지만 여전히 KeyCompareFunctor 인수의 기본값을 사용하고 싶습니다. 그런 다음 이것을 써야합니다.

MyClass<MyKeyType, MyValueType, AnObnoxiouslyLongSequenceOfCharacters<MyKeyType>, MyCustomValueCompareFunctor> myObject;

내가 세 번째 인수를 어떻게 든 생략하고 이것을 작성할 수 있다면 훨씬 더 편리 할 것입니다.

MyClass<KeyType, ValueType, MyCustomValueCompareFunctor> myObject;

MyCustomValuecompareFunctor는 MyKeyType 유형의 객체가 아닌 유형의 MyValueType의 객체에서만 작동하기 때문에 컴파일러는 적어도 이론적으로 내가 여기서 의미하는 바를 해결할 수있는 것처럼 보입니다.

C ++ 에서이 작업을 수행하는 방법이 있습니까?

도움이 되었습니까?

해결책

일반적으로 템플릿과 함수 또는 메소드 모두에서 C ++는 기본값을 사용할 수 있습니다. 후행 매개 변수 - 탈출구가 없습니다.

단축하려면 템플릿이나 매크로를 권장합니다 AnObnoxiouslyLongSequenceOfCharacters<MyKeyType> 에게 Foo<MyKeyType> - 완벽하지는 않지만 아무것도 아닌 것보다 낫습니다.

다른 팁

아니요. 가장 가까운 것은 사용자가 Sentinel 유형을 지정할 수 있도록하는 것입니다. void - "기본값을 여기에 사용"하고 클래스 내에서 템플릿 메타 마법을 사용합니다. typedef 실제 기본값 인 경우 void 당신에게 주어졌습니다. 그러나 이것은 아마도 가독성 관점에서 좋은 생각이 아닐 것입니다.

매개 변수 부스트 그리고 매개 변수라는 이름이 부스트 그래프를 부스트합니다 템플릿 함수/메소드의 이름 지정 매개 변수를 향한 노력입니다. 그들은 당신이 선호하는 순서대로 주장을 제공 할 기회를줍니다. 일부 인수는 기본값이있는 선택적 일 수 있습니다.

템플릿 인수에 동일한 접근법이 적용될 수 있습니다. n 템플릿 인수 + p 옵션을 갖는 대신 n + 1 템플릿 인수로 클래스를 만듭니다. 마지막은 생략 할 수있는 "이름"매개 변수를 보유합니다.

이 답변은 아직 완성되지 않았지만 좋은 출발이되기를 바랍니다!

대안 옵션은 특성 클래스를 사용하는 것입니다.

template <class KeyType>
class KeyTraits
{
  typedef AnObnoxiouslyLongSequenceOfCharacters<KeyType> Compare;
};

template <class ValueType>
class ValueTraits
{
  typedef AnObnoxiouslyLongSequenceOfCharacters<ValueType>  Compare;
};

template<class KeyType class ValueType>
class MyClass
{
  typedef KeyTraits<KeyType>::Compare KeyCompareFunctor;
  typedef ValueTraits<ValueType>::Compare KeyCompareFunctor;
};

그런 다음 키에 대해 다른 비교 함수가 필요한 유형이있는 경우 해당 케이스의 KeyTraits 유형을 명시 적으로 전문화하게됩니다. 다음은 우리가 그것을 바꾸는 예입니다 int:

template <>
class KeyTraits<int>
{
  typedef SpecialCompareForInt Cmopare;
};

상속을 사용하고 다음과 같이 작동하는 또 다른 옵션이 있습니다. 마지막 두 인수의 경우, 필요한 유형을 생성하는 데 사용할 수있는 두 개의 멤버 템플릿이있는 클래스에서 사실상 상속되는 클래스를 사용합니다. 상속은 가상이기 때문에 선언 한 Typedefs는 아래에 표시된 것처럼 상속 재산간에 공유됩니다.

template<class KeyType, 
         class ValueType, 
         class Pol1 = DefaultArgument, 
         class Pol2 = DefaultArgument>
class MyClass {
    typedef use_policies<Pol1, Pol2> policies;

    typedef KeyType key_type;
    typedef ValueType value_type;
    typedef typename policies::
      template apply_key_compare<KeyType>::type 
      key_compare;
    typedef typename policies::
      template apply_value_compare<ValueType>::type 
      value_compare;
};

이제 사용하려는 기본 인수가 제공되는 기본 인수가 제공됩니다. 멤버 템플릿은 키 및 값 유형에 의해 매개 변수화됩니다.

struct VirtualRoot { 
  template<typename KeyType>
  struct apply_key_compare {
    typedef AnObnoxiouslyLongSequenceOfCharacters<KeyType> 
      type;
  };
  template<typename ValueType>
  struct apply_value_compare {
    typedef AnObnoxiouslyLongSequenceOfCharacters<ValueType> 
      type;
  };
};

struct DefaultArgument : virtual VirtualRoot { };

template<typename T> struct KeyCompareIs : virtual VirtualRoot {
  template<typename KeyType>
  struct apply_key_compare {
    typedef T type;
  };
};

template<typename T> struct ValueCompareIs : virtual VirtualRoot {
  template<typename ValueType>
  struct apply_value_compare {
    typedef T type;
  };
};

지금, use_policies 모든 템플릿 인수에서 파생됩니다. 파생 클래스 VirtualRoot 기지에서 멤버를 숨기고, 파생 클래스의 구성원은 기본 구성원보다 우세하며, 상속 트리의 다른 경로에 의해 기본 등급 멤버에 도달 할 수 있지만 사용됩니다.

유형의 객체를 만들지 않기 때문에 가상 상속에 대한 비용을 지불하지 않습니다. use_policies. 가상 상속 만 사용하여 지배 규칙을 사용합니다.

template<typename B, int>
struct Inherit : B { };

template<class Pol1, class Pol2>
struct use_policies : Inherit<Pol1, 1>, Inherit<Pol2, 2>
{ };

우리는 잠재적으로 같은 클래스에서 두 번 이상 파생되기 때문에 클래스 템플릿을 사용합니다. Inherit: 같은 클래스를 직접 두 번 상속하는 것은 금지됩니다. 그러나 간접적으로 상속하는 것은 허용됩니다. 이제 다음과 같은 모든 것을 사용할 수 있습니다.

MyClass<int, float> m;
MyClass<float, double, ValueCompareIs< less<double> > > m;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top