2017-12-14 1 views
0

구조체가 하나 있고 각각이 하나의 열거 형을 멤버로 보유한다고 가정합니다. 내가 코드 예제처럼, 구조체의 멤버에 구조체의 방법 만 따라 호출 할 :구조체 멤버로 템플릿을 추론하는 방법

#include <iostream> 
#include <string> 
#include <type_traits> 

enum class Type{ 
    lowercase = 0, 
    uppercase 
}; 

struct Low{ 
    static constexpr Type cp = Type::lowercase; 
}; 

struct Up{ 
    static constexpr Type cp = Type::uppercase; 
}; 


template<typename Case, typename=void> 
struct Printer 
{ 
    void print_g(const std::string& s){ 
     std::cout << "just s: " << s << std::endl; 
    } 
}; 

template<typename X> 
struct Printer<X, std::enable_if_t<X::cp == Type::lowercase, void>> 
{ 
    void print_g(const std::string& s){ 
     std::cout << "lowercase " << std::nouppercase << s << std::endl; 
    } 
}; 

template<typename X> 
struct Printer <X, std::enable_if_t<X::cp == Type::uppercase, void>> 
{ 
    void print_g(const std::string& s){ 
     std::cout << "uppercase " << std::uppercase << s << std::endl; 
    } 
}; 

int main() 
{ 
    Printer<Low> pl; 
    pl.print_g("hello1"); 
    Printer<Up> p2; 
    p2.print_g("hello2"); 
} 

그러나이 솔루션은 나에게 매우 우아한 보이지 않는다. 특히 부분 typname = void 첫 번째 템플릿에. 그런 다음 코드가 컴파일됩니다. 왜 그런 경우입니까? 그리고이 템플릿 전문 분야에 대한 더 나은 (더 우아한) 솔루션이 있습니까?

답변

1

C++ 17에서는 if constexpr를 사용할 수 있습니다

template <typename X> 
struct Printer 
{ 
    void print_g(const std::string& s) 
    { 
     if constexpr(X::cp == Type::lowercase) 
     { 
      std::cout << "lowercase " << std::nouppercase << s << std::endl; 
     } 
     else if constexpr(X::cp == Type::uppercase) 
     { 
      std::cout << "uppercase " << std::uppercase << s << std::endl; 
     } 
     else 
     { 
      std::cout << "just s: " << s << std::endl; 
     } 
    } 
}; 

당신이 C++ (17)에 대한 액세스 권한이없는 경우이 옵션을 고려 : 일반 if

  • 사용. .. else 성명. 당신의 예제에서 조건 적으로 컴파일 될 필요가있는 코드는 없습니다.

  • static_if을 C++로 구현하십시오. 14. 여기가 준 이야기는 그것을 수행하는 방법에 대해 설명 것 : Implementing static control flow in C++14

+0

니스 :) 고마워요! – anicicn

+0

그리고 C++ 14 가지 방법이 있습니까? 저는 컴파일러 버전이 제한되어 있습니다. – anicicn

+0

@anicicn : 특별한 경우에, 당신은 일반적인'if' 문을 사용할 수 있습니다. –

1

할 수 있습니다 LowUp에 대한 fully specializePrinter.

template<class Case> 
struct Printer 
{ 
    void print_g(const std::string& s) { 
     std::cout << "just s: " << s << std::endl; 
    } 
}; 

template<> 
struct Printer<Low> 
{ 
    void print_g(const std::string& s) { 
     std::cout << "lowercase " << std::nouppercase << s << std::endl; 
    } 
}; 

template<> 
struct Printer<Up> 
{ 
    void print_g(const std::string& s) { 
     std::cout << "uppercase " << std::uppercase << s << std::endl; 
    } 
}; 

열거 형이 전혀 작동하지 않는다는 것에 주목하십시오. 열거 형을 전문화해야하는 경우에도 그렇게 할 수 있습니다.

template<Type Case> 
struct PrinterHelper 
{ 
    void print_g(const std::string& s) { 
     std::cout << "just s: " << s << std::endl; 
    } 
}; 

template<> 
struct PrinterHelper<Type::lowercase> 
{ 
    void print_g(const std::string& s) { 
     std::cout << "lowercase " << std::nouppercase << s << std::endl; 
    } 
}; 

template<> 
struct PrinterHelper<Type::uppercase> 
{ 
    void print_g(const std::string& s) { 
     std::cout << "uppercase " << std::uppercase << s << std::endl; 
    } 
}; 

template<class Case> 
using Printer = PrinterHelper<Case::cp>; 
1

I 가능성이 단지와 함께 갈 것입니다 :

enum struct Casing 
{ 
    Lower, 
     Upper 
}; 
template<Casing> 
struct printer; 
template<> 
struct printer<Casing::Lower> 
{ 
    ... 
}; 
template<> 
struct printer<Casing::Upper> 
{ 
... 
}; 
관련 문제