2015-10-29 15 views
11

Şifreli başlık için özür dilerim.Bir akıllı işaretçiye sarılmış bir sınıfa üye olmanın daha basit bir yolu var mı?

struct TestNode { 
    using CostType = double; 
}; 
Böyle bir sınıf şablonu tanımlayabilme istiyorum

: Bu tanım varsayalım Yukarıdaki tanımda

template <typename NodeP, 
      typename MyPolicy = /* CostType of the node type corresponding to NodeP */ > 
struct TT { 
}; 

, NodeP olabilir ya basit veya akıllı işaretçi için TestNode gibi CostType'u tanımlayan bir sınıf. Sorun: MyPolicy şablon parametresinin NodeP'a karşılık gelen düğüm tipinin CostType olması için nasıl bir varsayılan değer belirtebilir?

İşte benim çözüm şimdiye kadar geçerli: Bu sorunun daha basit bir yaklaşım

// like std::remove_pointer, but works with smart pointers as well 
template <typename PT> struct my_remove_pointer { 
    using type = typename 
     std::remove_reference< decltype(*((PT)nullptr)) >::type; 
}; 

struct TestNode { 
    using CostType = double; 
}; 

template <typename NodeP, 
      typename MyPolicy = typename my_remove_pointer<NodeP>::type::CostType> 
struct TT { 
}; 

var mı? Özellikle, çözümü daha basit hale getirebilecek standart bir kütüphane tesisimi eksik miyim? Akıllı işaretçi dereferencing ve .get() desteklediğinden

+4

'std :: ile ikame edilebilir ((PT) nullptr) declval () '. – Jarod42

+0

ve aşağıdaki ad kullanabilirsiniz: 'template my_remove_poiner_t = typename std :: remove_reference ())> :: type;' – Jarod42

cevap

7

pointer_traits adlandırılan standart kütüphanede bir yardımcı sınıf vardır Şimdi

template<typename T> 
using remove_pointer_t = typename my_remove_pointer<T>::type; 

template<typename T> 
using cost_type_t = typename remove_pointer_t<T>::CostType; 

biraz daha okunabilir olabilir. Tam olarak istediğin gibi görünüyor.

run online

#include <iostream> 
#include <memory> 
#include <typeinfo> 

struct TestNode { 
    using CostType = double; 
}; 

template <typename NodeP, 
      typename MyPolicy = typename std::pointer_traits<NodeP>::element_type::CostType> 
struct TT { 
    typedef MyPolicy xxx; 
}; 

int main() { 
    TT<TestNode*>::xxx a = 2.8; 
    TT<std::unique_ptr<TestNode>>::xxx b = 3.14; 
    std::cout << a << std::endl; 
    std::cout << b << std::endl; 
    return 0; 
} 
0

, biz altta yatan tipini almak için void_t kullanarak bir tür özelliği yazabilir: Henüz olmayan işaretçileri desteklemek gerekiyor olursa

template <typename... > 
using void_t = void; 

// base case: not any kind of pointer 
template <typename T, typename = void> 
struct underlying_type { 
    using type = T; 
}; 

// raw pointer 
template <typename T, typename = void> 
struct underlying_type<T*, void> { 
    using type = T; 
}; 

// smart pointer 
template <typename T> 
struct underlying_type<T, void_t< 
       decltype(*std::declval<T>()), 
       decltype(std::declval<T>().get()) 
       >> 
{ 
    using type = std::remove_reference_t< 
        decltype(*std::declval<T>()) 
       >; 
}; 

template <typename T> 
using underlying_type_t = typename underlying_type<T>::type; 

(I' m emin değilim), o zaman sadece yapabilirsiniz:

template <typename T> 
using underlying_type_t = std::remove_reference_t<decltype(*std::declval<T>())>; 

iki şekilde de, takma adına sahip bir zamanlar:

template <typename NodeP, 
      typename MyPolicy = underlying_type_t<NodeP>::Cost> 
struct TT { ... }; 
1

bazı usings ile Kuralların

template <typename NodeP, 
      typename MyPolicy = cost_type_t<NodeP>> 
struct TT { 
}; 
İlgili konular