2017-09-12 14 views
5

Tôi muốn sử dụng if constexpr thay vì gửi thẻ, nhưng tôi không chắc chắn cách sử dụng thẻ. Mã ví dụ bên dưới.nếu constexpr thay vì gửi thẻ

template<typename T> 
struct MyTag 
{ 
    static const int Supported = 0; 
}; 

template<> 
struct MyTag<std::uint64_t> 
{ 
    static const int Supported = 1; 
}; 

template<> 
struct MyTag<std::uint32_t> 
{ 
    static const int Supported = 1; 
}; 

class MyTest 
{ 
public: 
    template<typename T> 
    void do_something(T value) 
    { 
     // instead of doing this 
     bool supported = MyTag<T>::Supported; 

     // I want to do something like this 
     if constexpr (T == std::uint64_t) 
      supported = true; 
    } 
}; 
+2

Bạn không thể "gọi" 'toán tử == 'trên các loại; điều đó là vô nghĩa. Bạn có thể làm một cái gì đó tương tự với một thư viện như tăng hana: 'nếu constexpr (hana :: type_c == hana :: type_c )'. Bạn cũng có thể sử dụng 'std :: is_same':' nếu constexpr (std :: is_same_v ) ' – Justin

+0

Các loại không phải là giá trị, bạn không thể so sánh chúng như thế. – Rakete1111

+0

@ Rakete1111 Vâng tôi biết rằng tôi không thể so sánh chúng như thế, đó là câu hỏi là gì, làm thế nào tôi nên làm điều đó .... và tại sao downvote? – 0xBADF00

Trả lời

3

Một cách là xác định vị từ constexpr kiểm tra loại đối số của nó, sau đó chuyển đổi constexpr thành kết quả của vị từ đó.

Tôi nghĩ rằng cách này là tốt đẹp bởi vì nó tách logic chức năng từ logic điều kiện tiên quyết.

#include <iostream> 
#include <cstddef> 
#include <type_traits> 

class MyTest 
{ 
public: 
    template<typename T> 
    void do_something(T value) 
    { 
     // define our predicate 
     // lambdas are constexpr-if-possible in c++17 
     constexpr auto is_supported = [](auto&& x) { 
      if constexpr (std::is_same<std::decay_t<decltype(x)>, std::uint64_t>()) 
       return true; 
      else 
       return false; 
     }; 

     // use the result of the predicate   
     if constexpr (is_supported(value)) 
     { 
      std::cout << "supported\n"; 
     } 
     else 
     { 
      std::cout << "not supported\n"; 
     } 
    } 
}; 

int main() 
{ 
    auto t = MyTest(); 

    t.do_something(int(0)); 
    t.do_something(std::uint64_t(0)); 
    t.do_something(double(0)); 
    t.do_something(static_cast<unsigned long>(0)); // be careful with std::uint_xx aliases 

} 

kết quả ví dụ:

not supported 
supported 
not supported 
supported 

Một cách khác để thể hiện này có thể là:

class MyTest 
{ 
public: 

    template<class T> 
    static constexpr bool something_possible(T&&) 
    { 
     return std::is_same<std::decay_t<T>, std::uint64_t>(); 
    } 

    template<typename T> 
    void do_something(T value) 
    { 
     // switch behaviour on result of constexpr predicate  
     if constexpr (something_possible(value)) 
     { 
      std::cout << "supported\n"; 
     } 
     else 
     { 
      std::cout << "not supported\n"; 
     } 
    } 
}; 
+0

cảm ơn câu trả lời rất tốt đẹp, và std :: phân rã là cần thiết nếu T là một con trỏ hoặc tài liệu tham khảo, phải không? – 0xBADF00

+0

@ 0xBADF00 dải phân rã khỏi const, tham chiếu, v.v. để bạn có thể so sánh các loại cơ bản. –

Các vấn đề liên quan