模板特化 - 提供可选模板
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) };
}
选项#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) };
}
选项#3
C++03 版本,std::vector
、std::list
和 std::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));
}
测试:
std::vector<double> v = Converter::convert<double, std::vector>(42);
double d = Converter::convert<double>(42);
我在模板专业化方面有点吃力。
假设我正在实现一个可以在不同对象之间进行转换的 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) };
}
选项#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) };
}
选项#3
C++03 版本,std::vector
、std::list
和 std::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));
}
测试:
std::vector<double> v = Converter::convert<double, std::vector>(42);
double d = Converter::convert<double>(42);