2015-10-29 5 views
11

謎のタイトルに対する謝罪。この定義を仮定しますスマートポインタでラップされたクラスのメンバに簡単にアクセスできる方法はありますか?

struct TestNode { 
    using CostType = double; 
}; 

私はこのようなクラステンプレートを定義できるようにしたいと思います:上記の定義では

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

NodeP単純またはスマートポインタへのいずれかになりますCostTypeを定義するクラス、たとえばTestNodeです。問題:NodePに対応するノードタイプのCostTypeであるために、MyPolicyテンプレートパラメータのデフォルト値をどのように指定できますか?ここで

は、これまでのところ私のソリューションです:

// 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 { 
}; 

は、この問題に対する簡単な方法はありますか?特に、ソリューションをよりシンプルにする標準的なライブラリ機能が欠けていますか?スマートポインタを逆参照して.get()サポートしているので

+4

'((PT)nullptr)' 'のstd :: declval () 'で置き換えられてもよいです。 – Jarod42

+0

を使用し、別名を使用して使用します: 'テンプレート my_remove_poiner_t = typename std :: remove_reference ())> :: type;' – Jarod42

答えて

7

pointer_traitsと呼ばれる標準ライブラリのヘルパークラスがあります今すぐ

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; 

もう少し読みやすいかもしれません。それはまさにあなたが望むもののようです。

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

は、我々が基になる型を取得するためにvoid_tを使用して型形質を書くことができます:あなたがいないが非ポインタをサポートする必要があります場合

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」メートルわからない)、あなたは簡単に行うことができます。

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

いずれかの方法で、あなたは別名たら:

1

は、いくつかのusingsで、私はあなたのコード

template <typename NodeP, 
      typename MyPolicy = cost_type_t<NodeP>> 
struct TT { 
}; 
関連する問題