Here is a piece of code
// check if type of static array
template <class T>
struct ABIStaticArray : std::false_type //#1
{
};
// stringN type => bytesN
template <std::size_t N>
struct ABIStaticArray<std::array<char, N>> : std::false_type //#2
{
};
// a fixed-length array of N elements of type T.
template <class T, std::size_t N>
struct ABIStaticArray<std::array<T, N>> : std::true_type //#3
{
};
// fixed length of type, default 1 except static array type
template <class T, class Enable = void>
struct Length //#4
{
enum
{
value = 1
};
};
// length of static array type
template <class T>
struct Length<T, typename std::enable_if<ABIStaticArray<T>::value>::type> //#5
{
enum
{
value = std::tuple_size<T>::value * Length<typename std::tuple_element<0, T>::type>::value
};
};
- Why does the std::enable_if in specialized template of Length only have the first parameter?
- If I pass in a StaticArray, how does it match the specialized template of Length, if the value of first param of std::enable_if in specialized template of Length is true, the specialized template will become:
template <class T>
struct Length<T, void>
{
enum
{
value = std::tuple_size<T>::value * Length<typename std::tuple_element<0, T>::type>::value
};
};
why need this specialized template, what is the difference with the basic template of Length? the call of Length likes:
Length<std::array<int, 5>>::value
the result is 5
Please help, thanks very much!
CodePudding user response:
Let's see what is happening step by step. When you wrote:
Length<std::array<int, 5>>::value
Step 1) The template parameter T
for Length
is std::array<int, 5>
Step 2) Now there are two options that can be used. Either the primary template template <class T, class Enable = void>
labeled as #4
or the specialization for static array #5
. We want to find which one should be used. For this the condition typename std::enable_if<ABIStaticArray<std::array<int, 5>>::value>::type
is tested.
Step 3) Now, ABIStaticArray<std::array<int, 5>>
uses the 2nd specialization labeled as #3
because it is more specialized than the first specialization #2
and from the primary template #1
.
Step 4) Since the second specialization is used, std::enable_if<ABIStaticArray<std::array<int, 5>>::value
evaluates to true
so that typename std::enable_if<ABIStaticArray<std::array<int, 5>>::value>::type
evaluates to void
.
Basically, the specialization of Length
is preferred over the primary template.
Step 5) Since the specialization of Length
is selected the value
is calculated using value = std::tuple_size<std::array<int, 5>>::value * Length<typename std::tuple_element<0, std::array<int, 5>>::type>::value
which comes out to be 5
.
To confirm this I modified your program slightly:
// length of static array type
template <class T>
struct Length<T, typename std::enable_if<ABIStaticArray<T>::value>::type> //#5
{
enum
{
value = std::tuple_size<T>::value * Length<typename std::tuple_element<0, T>::type>::value
};
Length()
{
std::cout <<"specialization #5"<<std::endl;
}
};
int main()
{
Length<std::array<int, 5>> v; //will use the specialization of Length
}
The output of the program is:
specialization #5