[英]How can I use `std::array` for a template parameter of the form `template<typename> class`?
請考慮以下tree
類
template<typename T, template<typename> class Tuple>
class tree
{
private:
T m_value;
Tuple<tree> m_children;
};
template<typename T, std::size_t N>
using static_tree = tree<T, std::array<T, N>>;
這沒有明確的定義。 std::array<T, N>
不是Tuple
的合適模板參數。 我假設static_tree
的意圖是明確的。 我們可以做點什么
template<std::size_t N>
struct helper
{
template<typename T>
using type = std::array<T, N>;
};
template<typename T, std::size_t N>
using static_tree = tree<T, helper<N>::template type>;
沒有helper
類還有其他選擇嗎?
而不是將輔助函數作為std::array
的例外,我建議將其作為規則。 不使用模板模板參數,而是使用元函數類參數。 當所有地方都是類型(避免模板模板和非類型參數)時,模板元編程會輕松得多:
template<typename T, typename TupleMfn>
class tree
{
private:
using Tuple = TupleMfn::template apply<tree>;
T m_value;
Tuple m_children;
};
有:
template <size_t N>
struct array_builder {
template <class T>
using apply = std::array<T, N>;
};
template <typename T, size_t N>
using static_tree = tree<T, array_builder<N>>;
這樣可以更容易地與其他類型的容器一起使用,因為我們可以為模板模板創建一個包裝器,為我們提供一個元函數:
template <template <typename...> class X>
struct as_metafunction {
template <class... Args>
using apply = X<Args...>;
};
template <typename T>
using vector_tree = tree<T, as_metafunction<std::vector>>;
如果你感覺特別激動,你可以提供一個元編程友好版本的std::array
:
template <class T, class N>
struct meta_array : std::array<T, N::value> // obviously I am terrible at naming things
{ };
template <size_t N>
using size_t_ = std::integral_constant<size_t, N>;
然后提供tree
占位符args以應用:
template <class T, size_t N>
using static_tree = tree<T, meta_array<_, size_t_<N>>>;
template <class T>
using vector_tree = tree<T, std::vector<_>>;
我認為你的問題包含一個與你明確提出的問題不同的基本問題(它在本回答的前一次迭代中讓我失望了)。 結合你問題的不同部分,你實際上是在嘗試實例化一些樹類,它的成員也是同一個類的std::array
。 這顯然是不可能的。 您可能希望樹應該包含一些指針 Tuple
(智能或其他)。
一種方法是使用你的助手類,但將類修改為
template<typename T, template<typename> class Tuple>
class tree
{
// Indirection (I'm omitting the question of whether these should be
// smart pointers.
Tuple<tree<T, Tuple> *> m_children;
};
一種不同的方法會使Tuple
成為常規模板參數,如下所示:
#include <array>
#include <type_traits>
template<typename T, class Tuple>
class tree
{
private:
static_assert(
std::is_same<void *, typename Tuple::value_type>::value,
"Tuple must be a container of void *");
private:
T m_value;
Tuple m_children;
};
template<typename T, std::size_t N>
using static_tree = tree<T, std::array<void *, N>>;
int main()
{
static_tree<int, 8> t;
}
一方面,輔助類已被淘汰。 OTOH, Tuple
是void *
的容器:實例化器知道這一點,並且類內部需要執行強制轉換。 這是一個權衡。 我會堅持你的原始版本(當然有修改建議)。
除了邏輯上,類X不能包含類X的實際實例的多個副本。
如果我們有
struct X {
std::array<X, 2> data;
};
X
的唯一可能大小是無窮大,因為sizeof(X)
= 2*sizeof(X)
,並且C ++中的所有類型都有sizeof(X)>=1
。
C ++不支持無限大類型。
您的第二個問題是類型實例不是模板。
template<typename T, template<typename> class Tuple>
class tree
這需要一個類型T
和一個template
Tuple
。 第二個參數不是類型 。
template<typename T, std::size_t N>
using static_tree = tree<T, std::array<T, N>>;
在這里,你的第二個參數是一個類型 ,而不是一個模板。
template<std::size_t N>
struct array_of_size {
template<class T>
using result=std::array<T,N>;
};
template<typename T, std::size_t N>
using static_tree = tree<T, array_of_size<N>::template result>;
除了上述“無限大小問題”之外,還能解決你的問題。 這里我們將模板array_of_size<N>::result
傳遞給tree
。
要解決無限大小問題, 必須在數組中存儲指針(或等效的東西)。 所以我們得到:
template<std::size_t N>
struct array_of_ups_of_size {
template<class T>
using result=std::array<std::unique_ptr<T>,N>;
};
template<typename T, std::size_t N>
using static_tree = tree<T, array_of_ups_of_size<N>::template result>;
現在你的static_tree有N
個子節點,每個子節點都是一個類似static_tree
的unique_ptr
。
由於析構函數問題,這仍然不起作用。
template<typename T, template<typename> class Tuple>
class tree
{
private:
T m_value;
Tuple<tree> m_children;
public:
~tree();
};
template<typename T, template<typename> class Tuple>
tree<T,Tuple>::~tree() = default;
我認為以上修復了它,看起來很奇怪。
基本上,當您創建子數組時,樹類型不完整。 在銷毀時,調用delete。 那時,樹必須完整。 通過推遲dtor,我們希望能夠處理這個問題。
我不確定模板是否需要這種技術,但它適用於非模板類。
或者您可以按照建議實現模板參數綁定(稍微比您的helper
更通用):
template<std::size_t N, template<typename,std::size_t> class T>
struct bind2nd
{
template<typename F>
using type = T<F,N>;
};
template<std::size_t N, typename T>
using static_tree = tree<T, bind2nd<N,std::array>::template type>;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.