2016-12-10 67 views
2

比方说,我想要一个class/struct类型,从integral_constant<size_t, N>继承其中N是维度和尺寸如下实现:获取一个std ::矢量/ STD的尺寸::阵列的数目

template<class T> 
struct dimension; 

template<class T> 
struct dimension<vector<T>> : integral_constant<size_t, 1> {}; 

template<class T> 
struct dimension<vector<vector<T>>> : integral_constant<size_t, 2> {}; 

然后

cout << dimension<vector<int>>::value;   // 1 
cout << dimension<vector<vector<int>>>::value; // 2 

但显然这是不完美的,作为维数可以是无限的(理论上)。有没有办法实现这个通用的解决方案?

建议:我去这个方向,但没有进一步的:

template<class T, class... Tn> 
struct dimension<vector<Tn...>> : integral_constant<size_t, sizeof...(Tn)> {}; 

由于std::vector具有其他模板参数这是行不通的。

回答

2

您可以为std::vector做到这一点(注意,std::vector的模板参数列表的长度大于1):

template<typename T> 
struct dimension { static constexpr std::size_t value = 0; }; 

template<typename T, typename... V> 
struct dimension<std::vector<T, V...>>{ 
    static constexpr std::size_t value = 1 + dimension<T>::value; 
}; 

这工作,而不是为std::array

template<typename> 
struct dimension { static constexpr std::size_t value = 0; }; 

template<typename T, std::size_t N> 
struct dimension<std::array<T, N>>{ 
    static constexpr std::size_t value = 1 + dimension<T>::value; 
}; 

它遵循最小的工作示例:

#include<vector> 
#include<iostream> 

template<typename T> 
struct dimension { static constexpr std::size_t value = 0; }; 

template<typename T, typename... V> 
struct dimension<std::vector<T, V...>>{ 
    static constexpr std::size_t value = 1 + dimension<T>::value; 
}; 

int main() { 
    std::cout << dimension<std::vector<std::vector<int>>>::value << std::endl; 
} 
+0

这是我的,尽管如此。它必须受到限制。 – DeiDei

+0

@ T.C。对。固定。 – skypjack

3

有点难以定义“什么是容器”。以下检查为value_type,iteratorconst_iterator嵌套的typedefs。根据需要调整void_t检查。 (例如,如果您只想将可以下标的东西识别为容器,则将decltype(std::declval<T&>()[0])添加到列表中。)

请注意,dimension_impl的专业化调用dimension。这允许您专门为容器类物品专门设计dimension,您不想将其视为容器(想起std::string)。

template<class T> struct dimension; 

namespace details {  
    template<class T, class = void> 
    struct dimension_impl { 
     static constexpr std::size_t value = 0; 
    }; 

    template<class T> 
    struct dimension_impl<T, std::void_t<typename T::value_type, 
             typename T::iterator, 
             typename T::const_iterator>> { 
     static constexpr std::size_t value = 1 + dimension<typename T::value_type>::value; 
    }; 
} 

template<class T> 
struct dimension : std::integral_constant<std::size_t, 
              details::dimension_impl<T>::value> {}; 
+0

这样你就会报告'std :: vector >'的维数为2 – skypjack

+0

@skypjack这对我来说很好。 'list '是一个容器。如果有人只想识别'std :: vector'和'std :: array',他们有你的答案。 (我质疑这样做的有用性,考虑到这里有许多'vector''类容器。) –

+0

我得到了这个问题 - 我想要找到一个向量链或一个array_链的维数。你会允许包含这两种类型的链(以及所有其他容器)。 OP想要什么? – skypjack