模板特化 - 提供可选模板

Template specializations - giving an optional template

我在模板专业化方面有点吃力。

假设我正在实现一个可以在不同对象之间进行转换的 class。在这里,为了简单起见,我将在基本类型之间进行转换。

class Converter
{
    public:
       Converter() {};

    template <typename ConvT,
              typename FromT>
    static
    ConvT
    convert(From type);
};


template <typename ConvT,
          typename FromT>
ConvT
Converter::convert(FromT type)
{
   return static_cast<ConvT>(type);
}

template <>
double
Converter::convert<double,int>(int type)
{
  return 22.2;
}

现在我可以做这样的事情了

float myFloat = Converter::convert<float>(5);
double myTwentyTwoPointTwo = Converter::convert<double>(42);

我还希望能够指定一个可选的模板参数,它将成为该类型的容器。

// Retrns a std::vector<dobule> with one element, 22.2.
std::vector<double> myDoubleVec = Converter::convert<double, std::vector>(42);

有没有办法扩展这个 class 使其具有此功能?

编辑:这很好:

Converter::convert<double, int, std::vector>(42);

最简单的方法是直接传递容器类型:

#include <vector>

template<typename C, typename T>
C ConvertAndPutIntoContainer(T t) 
{
    C c;
    c.push_back(static_cast<typename C::value_type>(t));
    return c;    
}

// usage
auto x = ConvertAndPutIntoContainer<std::vector<double>>(23);

选项#1

处理两种转换的单一主模板 - 到标量或容器:

template <typename T>
using identity = T;

struct Converter
{
    template <typename ConvT,
              template <typename...> class ConT = identity,
              typename FromT>
    static ConT<ConvT> convert(FromT type);
};

template <typename ConvT,
          template <typename...> class ConT,
          typename FromT>
ConT<ConvT> Converter::convert(FromT type)
{
    return ConT<ConvT>{ static_cast<ConvT>(type) };
}

DEMO 1

选项#2

容器的单独重载:

struct Converter
{
    //...

    template <typename ConvT,
              template <typename...> class ConT,
              typename FromT>
    static ConT<ConvT> convert(FromT type);
};

template <typename ConvT,
          template <typename...> class ConT,
          typename FromT>
ConT<ConvT> Converter::convert(FromT type)
{
    return ConT<ConvT>{ static_cast<ConvT>(type) };
}

DEMO 2

选项#3

C++03 版本,std::vectorstd::liststd::deque 容器的单独重载:

struct Converter
{
    //...

    template <typename ConvT,
              template <typename T, typename A = std::allocator<T> > class ConT,
              typename FromT>
    static ConT<ConvT> convert(FromT type);
};

template <typename ConvT,
          template <typename T, typename A = std::allocator<T> > class ConT,
          typename FromT>
ConT<ConvT> Converter::convert(FromT type)
{
    return ConT<ConvT>(1, static_cast<ConvT>(type));
}

DEMO 3

测试:

std::vector<double> v = Converter::convert<double, std::vector>(42);
double d = Converter::convert<double>(42);