2017-12-09 2 views
3
template<typename T, int V> 
class AwesomeClass // [1] 
{ 
public: 

    AwesomeClass(T baseValue) 
     : m_value(baseValue + V) 
    { 
    } 

    T get() const 
    { 
     return m_value; 
    } 

private: 

    T m_value; 
}; 

#ifdef USE_ALIAS_TEMPLATES // [2] 

template<typename T> 
using AwesomeClassWithOne = AwesomeClass<T, 1>; 

template<typename T> 
using AwesomeClassWithTwo = AwesomeClass<T, 2>; 

#else // [4] 

template<typename T> 
class AwesomeClassWithOne: public AwesomeClass<T, 1> 
{ 
    using AwesomeClass<T, 1>::AwesomeClass; 
}; 

template<typename T> 
class AwesomeClassWithTwo: public AwesomeClass<T, 2> 
{ 
    using AwesomeClass<T, 2>::AwesomeClass; 
}; 

AwesomeClassWithOne(int) -> AwesomeClassWithOne<int>; 
AwesomeClassWithTwo(int) -> AwesomeClassWithTwo<int>; 

#endif 

int main() 
{ 
    AwesomeClassWithOne firstObj(20); // [3] 
    AwesomeClassWithTwo secondObj(20); 

    return firstObj.get() + secondObj.get(); 
} 

나는 두 개의 템플릿 매개 변수 typename Tint V을 사용하는 클래스 AwesomeClass [1]을 가지고 있습니다. V은 클래스의 사용자에게 공개하고 싶지 않은 내부 세부 정보이므로 AwesomeClassWithOneAwesomeClassWithTwo과 같은 별칭을 제공하려는 경우 T을 템플릿 매개 변수로 사용하고 V은 이미 일부 값 (1 내 예에서는 각각 2).별칭 템플릿 또는 특수 파생 클래스?

별칭 템플릿이이 [2]에 적합하다고 보입니다. 그러나 C++ 17부터는 별칭 템플릿에 인수 차감을 사용할 수 없기 때문에 [3] 할 수 없습니다.

그래서 내가 원하는 "별칭"유형마다 새 파생 클래스를 만들고 기본 클래스의 모든 생성자를 상속 한 다음 자동 공제 작업을 수행하는 공제 안내서를 만듭니다 (기본 클래스 생성자는 일반 생성자처럼 자동 공제 가이드가 나타나지 않는 것 같습니다 (related question).

이 방법이 적절한 해결 방법으로 보입니까? 별칭 템플릿 솔루션과 비교하여 이상한 부작용을 예상 할 수 있습니까?

답변

1

사용 별칭 템플릿입니다.

클래스 템플릿 인수 공제가 별칭 템플릿에서 작동하지 않으며 그 의미가 명확하지 않지만 클래스 템플릿 인수 공제가 inherited constructors either과 작동한다고 명확하게 구분되지 않습니다.아직 공개 된 질문이므로 해결해야합니다.

어쨌든 새 유형 을 도입하고 싶지는 않습니다. 당신은 매우 AwesomeClass<T, 1> 유형 싶습니다. 따라서 AwesomeClassWithOne<T>AwesomeClass<T, 1>이 실제로 인 경우 일 경우 문제가 발생할 수 있습니다. 이것들은 여러분이 정말로 자신에게 들어가기를 원하는 종류의 문제가 아닙니다. 특히이 작업을 수행하는 유일한 이유가 클래스 템플릿 변수 공제를 허용하는 경우입니다.

경우 정말 우리가 작성하는 데 사용하는 것처럼, 단지 make_*() 도우미를 제공하는 기능이 필요합니다.

1

C++ 17에서는 유형 별명에 대한 공제 안내서를 허용하지 않습니다.

하지만 좋은 오래된 방법 (std::make_pair(), std::make_tuple(), std::make_unique() 등)을 사용할 수 있습니다.

모범

: 정의한 경우, 템플릿 인자의 순서를 전환하는 등의 makeAwesome() 함수

다음으로 호출

template <int V, typename T> 
AwesomeClass<T, V> makeAwesome (T && t) 
{ return { std::forward<T>(t) }; 

는, AwesomeClass<T, V> 오브젝트를 취득 V을 explicating 및 T을 추론 할 수 이하

auto firstObj = makeAwesome<1>(20); 

정수 V 부분에 사용자를 표시하지 않으려면

를 추가 할 수 있습니다.
template <typename T> 
auto makeAwesomeWithOne (T && t) 
{ return makeAwesome<1>(std::forward<T>(t)); } 

template <typename T> 
auto makeAwesomeWithTwo (T && t) 
{ return makeAwesome<2>(std::forward<T>(t)); } 

10 main()에 당신은

auto firstObj = makeAwesomeWithOne(20); 
auto secondObj = makeAwesomeWithTwo(20); 

내가 거의 동일하다 makeAwesomeWith 번호 기능을 많이 쓰는 짜증나 알고 쓸 수 있습니다.

오래된 C 스타일의 함수 매크로를 사용하면 (예 : IMHO,하지만 이런 상황에서 ... 증류됩니다.) 다음과 같이 자동으로 makeAwesomeWith-number 함수를 만들 수 있습니다.

#define MakeAwesomeWith(Str, Num) \ 
    template <typename T> \ 
    auto makeAwesomeWith ## Str (T && t) \ 
    { return makeAwesome<Num>(std::forward<T>(t)); } 

MakeAwesomeWith(One, 1); 
MakeAwesomeWith(Two, 2); 
// ... 

다음 은 전체 작업 (기반 매크로) 예를

#include <iostream> 
#include <utility> 

template <typename T, int V> 
class AwesomeClass 
{ 
    public: 
     AwesomeClass (T baseValue) : m_value(baseValue + V) 
     { } 

     T get() const 
     { return m_value; } 

    private: 
     T m_value; 
}; 

template <int V, typename T> 
AwesomeClass<T, V> makeAwesome (T && t) 
{ return { std::forward<T>(t) }; } 

#define MakeAwesomeWith(Str, Num) \ 
    template <typename T> \ 
    auto makeAwesomeWith ## Str (T && t) \ 
    { return makeAwesome<Num>(std::forward<T>(t)); } 

MakeAwesomeWith(One, 1); 
MakeAwesomeWith(Two, 2); 

int main() 
{ 
    auto firstObj = makeAwesomeWithOne(20); 
    auto secondObj = makeAwesomeWithTwo(20); 

    std::cout << (firstObj.get() + secondObj.get()) << std::endl; 
} 
관련 문제