这个问题需要更多准备,所以我首先提供一些代码,然后是确切的问题
假设我声明了以下类型
template<typename T>
struct some_type
{
T t_;
};
将使用像
这样的工厂函数构建typedef float numeric_type;
std::vector<std::string> construction_material;
//Push_back of strings in certain form...
std::vector<std::unique_ptr<some_type<numeric_type>> instances;
build_instances(construction_material.begin(), construction_material.end(), back_inserter(instances));
并且构造函数将类似之后的
template<typename input_iterator, typename output_iterator>
output_iterator build_instances(input_iterator begin, input_iterator end, output_iterator out)
{
for(input_iterator iter = begin; iter != end; ++iter)
{
//This won't work, but to illustrate some ideas...
//build_instance<std::iterator_traits<output_iterator>::value_type>(*iter)
}
//[...]
return *out;
}
template<typename T>
std::unique_ptr<some_type<T>> build_instance(std::string const& material)
{
static_assert(std::is_floating_point<T>::value == true, "The template type needs to be a floating point type.");
std::unique_ptr<some_instance<T>> instance(new some_instance<T>());
//Some processing...
return instance;
}
我知道我可以更改函数以返回某个容器(或者甚至可能会将容器类型模板化),例如
template<typename input_iterator, typename T>
std::vector<std::unique_type<T>> build_instances(input_iterator begin, input_iterator end,
output_iterator out)
{
//Likewise code to the previous snippets...
return ...
}
我无法解决的问题是:
标题How can I make this template method more elegant? (or: less explicit template parameters required)有类似的问题,它采用容器并将其转换为不同类型的容器。
修改 正如Jogojapan的评论所评论的那样,目前我正在改变输入
std::transform(construction_material.begin(), construction_material.end(), std::inserter(instances, instances.begin()), build_instance<numeric_type>);
但后续的函数调用也需要提供看起来我错了,但是为了教育的目的,是否有可能进一步减少输入数字类型并从迭代器推导出来的需要?numeric_type
typedef,这有点麻烦。我希望避免这种情况。
答案 0 :(得分:0)
侵入式解决方案是让some_type
公开其类型参数,方式std::unique_ptr<T, D>
通过element_type
公开其第一个参数(稍后我们将需要):
template<typename T>
struct some_type
{
// give it an appropriate meaningful name
using value_type = T;
value_type t_;
};
template<typename input_iterator, typename output_iterator>
output_iterator build_instances(input_iterator begin, input_iterator end, output_iterator out)
{
using pointer_type = typename std::iterator_traits<output_iterator>::value_type;
using value_type = typename pointer_type::element_type::value_type;
return std::transform(begin, end, out, build_instance<value_type>);
}
您还可以非侵入式地提取模板特化的第一个模板参数:
template<typename T>
struct first;
template<template<typename...> class Template, typename First, typename... Pack>
struct first<Template<First, Pack...>>> {
using type = First;
};
template<typename T>
using First = typename first<T>::type;
value_type
中的build_instances
别名将改为
using value_type = First<typename pointer_type::element_type>;
作为最后的评论,我发现build_instance
采用T
参数但构造some_type<T>
的实例有点奇怪。如果T
和T
的构造实例(可能T
被限制为some_type
的特化)。这也可以避免您的问题。