非类型模板参数可以在stl容器上完成吗?

时间:2019-09-23 09:37:56

标签: c++ c++11 templates containers c++-standard-library

ul {
    font-size: 0;
}

可以使用template<typename T,int nSize> T Sum(T (&parr)[nSize]) { T sum=0; for(int i = 0; i < nSize ;++i) { sum += parr[i]; } return sum; } int _tmain(int argc, _TCHAR* argv[]) { int nArr[] = {1,2,3,4}; int nSum = Sum(nArr); std::cout<<"Sum :"<<nSum; } 代替 array 。还是可以用任何stl容器替换 array

3 个答案:

答案 0 :(得分:4)

  

可以使用let current_slots = getCurrentSlotsAxios(group_id) console.log(current_slots + 1) // results in NaN whether I use parseInt or not :( 代替 array 。或者可以将 array 替换为   有什么stl容器?

不。这是不可能的,因为它们的类型不同。但是您可以通过以下方式概括给定的功能。

使模板函数接受容器的开始和结束迭代器。然后使用std::accumulate,对元素求和,这将对 any sequence containers 和数组起作用:

以下是示例代码:See live online

std::vector

输出

#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <numeric>  // std::accumulate
#include <iterator> // std::iterator_traits, std::cbegin, std::cend

template<typename Iterator>
constexpr auto Sum(Iterator begin, const Iterator end) -> typename std::iterator_traits<Iterator>::value_type
{
    using RetType = typename std::iterator_traits<Iterator>::value_type;
    return std::accumulate(begin, end, RetType{});
}

int main()
{
    int nArr[] = { 1,2,3,4 };
    std::vector<int> vec{ 1,2,3,4 };
    std::list<int> list{ 1,2,3,4 };
    // now you can
    std::cout << "Sum of array: " << Sum(std::cbegin(nArr), std::cend(nArr)) << "\n";
    std::cout << "Sum of vec: "   << Sum(std::cbegin(vec), std::cend(vec)) << "\n";
    std::cout << "Sum of list: "  << Sum(std::cbegin(list), std::cend(list)) << "\n";
}

答案 1 :(得分:2)

    ssl_certificate /etc/letsencrypt/live/funders-api.ninja/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/funders-api.ninja/privkey.pem; # managed by Certbot

将是template<typename T, int nSize> T sum(std::array<T, nSize> const&); 的等效签名。如您所见,签名已经有所不同。尝试对std::array执行相同操作注定会失败:

std::vector

您将如何在编译时知道向量中将驻留多少个元素???你根本不能。即使您在代码中明确指定了template<typename T, int nSize> T sum(std::vector<T> const&); ,e。 G。 nSize之后,该函数将始终尝试迭代恰好七个元素,如果元素较少,则会导致未定义的行为,如果元素较多,则将不计算多余的元素...

典型的做法是使用开始和结束迭代器,就像标准库的所有算法一样:

sum<std::vector<int>, 7>

您还可以基于此功能,为任意容器提供通用的重载,然后:

template <typename Iterator>
auto sum(Iterator begin, Iterator end) -> std::remove_reference_t<decltype(*begin)>
{
    using type = decltype(sum(begin, end)); // just not wanting to repeat all
                                            // that remove_reference stuff...
    type s = type();
    for( ; begin != end; ++begin)
    {
        s += *begin;
    }
    return s;
}

答案 2 :(得分:0)

如果编译器支持C ++ 17,则可以使用if constexpr语句编写单个函数。

例如

#include <iostream>
#include <vector>

template<typename T>
auto Sum( const T &container )
{
    if constexpr( std::is_array_v<std::remove_reference_t<T>> )
    {
        std::remove_extent_t<T> sum = 0;
        for ( const auto &item : container )
        {
            sum += item;
        }

        return sum;
    }
    else
    {
        typename T::value_type sum = 0;
        for ( const auto &item : container )
        {
            sum += item;
        }

        return sum;
    }
}

int main()
{
    int nArr[] = { 1, 2, 3, 4 };
    int nSum = Sum( nArr );
    std::cout << "Sum :"<<nSum << '\n';;

    std::vector<int> v = { 1, 2, 3, 4 };
    nSum = Sum( v );
    std::cout << "Sum :"<<nSum << '\n';;
}

程序输出为

Sum :10
Sum :10

但是最好将函数分为两个函数:一个用于数组,另一个用于标准容器。

#include <iostream>
#include <vector>

template<typename T, size_t N>
auto Sum( const T ( &a )[N] )
{
    T sum = 0;

    for ( const auto &item : a )
    {
        sum += item;
    }

    return sum;
}

template<typename T>
auto Sum( const T &container )
{
    typename T::value_type sum = 0;
    for ( const auto &item : container )
    {
        sum += item;
    }

    return sum;
}

int main()
{
    int nArr[] = { 1, 2, 3, 4 };
    int nSum = Sum( nArr );
    std::cout << "Sum :"<<nSum << '\n';;

    std::vector<int> v = { 1, 2, 3, 4 };
    nSum = Sum( v );
    std::cout << "Sum :"<<nSum << '\n';;
}
相关问题