Rafshan
Rafshan

Reputation: 13

Partial template specialization using STL

I have a function which has template class object as parameter. Its working fine with user defined template class object as paramerter but its giving arror with std::array object. If I am trying to execute this program

#include<iostream>
#include<array>

template<typename T1, int size>
void print(std::array<T1, size> &arr)
{
    for (auto ele : arr)
        std::cout << ele << " ";
}

template<int size>
void print(std::array<float, size> &arr)
{
    std::cout << "its float" << std::endl;
    for (auto ele : arr)
        std::cout << ele << " ";
}

int main()
{
    std::array<int, 3> arr{1,3,4};
    std::array<float, 2> ar2{1.3, 3.4};
    print(arr);
    print(ar2);
    return 0;
}

And getting this error

error: no matching function for call to ‘print(std::array<int, 3>&)’
     print(arr);

But when I am running this program then its working fine.

#include<iostream>
#include<array>

template<class T, int size>
class Template
{
    public:
    std::array<T, size> arr;
};

template<typename T1, int size>
void print(Template<T1, size> &obj)
{
    for (auto ele : obj.arr)
        std::cout << ele << " ";
}

template<int size>
void print(Template<float, size> &obj)
{
    for (auto ele : obj.arr)
        std::cout << ele << " ";
}

int main()
{
    Template<int, 3> array;
    array.arr[0] = 1;
    array.arr[1] = 2;
    array.arr[2] = 3;
    Template<float, 2> arr2;
    arr2.arr[0] = 2.3;
    arr2.arr[1] = 2.9;
    print(array);
    print(arr2);
    return 0;
}

I don't understand why std::array<T1, size> is not suitable match for std::array<int, 3> but class Template<T1,size> is suitable match for Template<int, 3>

Upvotes: 1

Views: 43

Answers (2)

songyuanyao
songyuanyao

Reputation: 172934

Because the 2nd template parameter's type of std::array is std::size_t, but not int; they don't match and cause template argument deduction on the non-type template parameter fails.

(emphasis mine)

If a non-type template parameter is used in the parameter list, and the corresponding template argument is deduced, the type of the deduced template argument ( as specified in its enclosing template parameter list, meaning references are preserved) must match the type of the non-type template parameter exactly, except that cv-qualifiers are dropped, and except where the template argument is deduced from an array bound—in that case any integral type is allowed, even bool though it would always become true:

Change the type to std::size_t.

template<typename T1, std::size_t size>
void print(std::array<T1, size> &arr)
{
    for (auto ele : arr)
        std::cout << ele << " ";
}

template<std::size_t size>
void print(std::array<float, size> &arr)
{
    std::cout << "its float" << std::endl;
    for (auto ele : arr)
        std::cout << ele << " ";
}

LIVE

Upvotes: 4

Goblinhack
Goblinhack

Reputation: 3088

You were close. Use size_t instead of int. This compiles:

#include <iostream>
#include <array>

template<typename T1, size_t size>
void print(std::array<T1, size> const &arr)
{
    for (auto ele : arr)
        std::cout << ele << " ";
}

template<size_t size>
void print(std::array<float, size> &arr)
{
    std::cout << "its float" << std::endl;
    for (auto ele : arr)
        std::cout << ele << " ";
}

int main()
{
    std::array<int, 3> arr{1,3,4};
    std::array<float, 2> ar2{1.3, 3.4};
    print(arr);
    print(ar2);
    return 0;
}

Upvotes: 0

Related Questions