如何结合模板部分特化和模板参数推演

How to combine template partial specialization and template argument deduction

本文关键字:参数 板部 何结合 结合      更新时间:2023-10-16

我的理解是,模板参数推导仅适用于函数模板,但函数模板不允许部分专用化。有没有办法同时实现这两个目标?

我基本上想实现一个带有签名的类似函数的对象(可以是函子)

template<class InputIterator1, class InputIterator2, class OutputIterator, int distribution>
void GetQuantity(InputIterator1 frist1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, double supply, double limit);

根据分布的价值,我想对这个模板进行一些专业化。当我调用这个函数时,我基本上不想指定所有的类型参数,因为它们很多(因此我需要参数推导)!

您可以使用在

分发上模板化的函子来实现这一点,并让推导在调用 operator() 时完成

template<int distribution>
struct GetQuantity {
    template<class InputIterator1, class InputIterator2, class OutputIterator>
    void operator()(
        InputIterator1 frist1, InputIterator1 last1, InputIterator2 first2, 
        OutputIterator result, double supply, double limit );
};
template<>
struct GetQuantity<0> {
    // specialized stuff
};

部分专用struct的替代方法是使用std::integral_constant重载:

template<class InputIterator1, class InputIterator2, class OutputIterator>
void GetQuantity(InputIterator1 first1, InputIterator1 last1,
                 InputIterator2 first2, OutputIterator result,
                 double supply, double limit,
                 std::integral_constant<int, 0>);

这可以通过调度程序调用:

template<int distribution,
         class InputIterator1, class InputIterator2, class OutputIterator>
void GetQuantity(InputIterator1 first1, InputIterator1 last1,
                 InputIterator2 first2, OutputIterator result,
                 double supply, double limit)
{
    GetQuantity(first1, last1, first2, result, supply, limit,
                std::integral_constant<int,distribution>{});
}

可以通过转换序列提供默认实现:

template<int dist>
struct der_int_const : std::integral_constant<int, dist>
{}
template<int distribution,
         class InputIterator1, class InputIterator2, class OutputIterator>
void GetQuantity(InputIterator1 first1, InputIterator1 last1,
                 InputIterator2 first2, OutputIterator result,
                 double supply, double limit, der_int_const<distribution>{});

还有另一种方法甚至可以部分专注于distribution参数(简化):

#include <iostream>
#include <type_traits>
struct X0{};
struct X1{};
template<int distribution, class It,
         class U = typename std::enable_if<distribution==0>::type>
void GetQuantity(It, X0={});
template<int distribution, class It,
         class U = typename std::enable_if<(distribution>1)>::type>
void GetQuantity(It, X1={});

C++03版本:

#include <boost/type_traits.hpp>

然后使用 boost::integral_constant 而不是 std::integral_constant

#include <boost/utility/enable_if.hpp>
struct X0{};
struct X1{};
template<int distribution, class It>
typename boost::enable_if_c<distribution==0>::type
GetQuantity(It, X0=X0()){ std::cout<<"0n"; }
template<int distribution, class It>
typename boost::enable_if_c<(distribution>1)>::type
GetQuantity(It, X1=X1()){ std::cout<<"1n"; }