我可以默认这个Transform模板函数的返回类型吗?

Can I default the return type of this Transform template function?

本文关键字:函数 返回类型 默认 Transform 我可以      更新时间:2023-10-16

目前,要使用以下…

template< class ResultCollection, class Collection, typename Transformation >
ResultCollection Transform(const Collection& c, Transformation t)
{
    ResultCollection result(c.size());
    transform(c.begin(), c.end(), result.begin(), t);
    return result;
}

…您需要提供返回类型:

auto result = Transform< std::vector<int> >( someInputCollection, [] (SomeType& element) { return ElementToInt(element); });

是否有可能默认模板参数,以便默认情况下您将获得包含lambda返回的任何类型元素的向量?

I got to this:

template< class Collection, typename Transformation, class ResultCollection = std::vector< std::result_of_t<Transformation> > >
ResultCollection Transform(const Collection& c, Transformation t)
{
    ResultCollection result(c.size());
    transform(c.begin(), c.end(), result.begin(), t);
    return result;
}

但这给了我这个:

C2783: 'ResultCollection Transform(const Collection &,Transformation)' : could not deduce template argument for 'ResultCollection'

我不知道如何修复它

您的代码有两个问题。第一个是缺失的typename s:

class ResultCollection = std::vector< typename std::iterator_traits<typename Collection::iterator>::value_type > 
                                      ^^^^^^^^                      ^^^^^^^^

但是第二个问题是你传递了完全错误的类型!如果您的Transformation实际上没有改变集合的值类型,那么这一切都很好,但是如果它这样做了呢?

std::vector<char> collection;
auto result = Transform(collection, [](char c) { return std::string(c, 1); });

您需要生成的vector包含Transformation给出的类型:

class ResultCollection = std::vector<
    std::result_of_t<Transformation(decltype(*std::declval<Collection>().begin()))>
>
而且,顺便说一句,如果结果类型不是默认可构造的呢?你假设它在这里:
ResultCollection result(c.size());

可能需要这样做:

ResultCollection result;
result.reserve(c.size());
std::transform(c.begin(), c.end(), std::back_inserter(result), t);

或真的:

ResultCollection result;
result.reserve(c.size());
for (const auto& elem : c) {
    result.push_back(t(elem));
}

您可以使用kennytm在此回答中提供的function_traits来获取lambda的返回类型并将其设置为默认值。使用它你会得到

template <typename T>
struct function_traits
    : public function_traits<decltype(&T::operator())>
{};
// For generic types, directly use the result of the signature of its 'operator()'
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
    enum { arity = sizeof...(Args) };
    // arity is the number of arguments.
    typedef ReturnType result_type;
    template <size_t i>
    struct arg
    {
        typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
        // the i-th argument is equivalent to the i-th tuple element of a tuple
        // composed of those arguments.
    };
};
template< class Collection, typename Transformation, class ResultCollection = std::vector< typename function_traits<Transformation>::result_type > >
ResultCollection Transform(const Collection& c, Transformation t)
{
    ResultCollection result(c.size());
    transform(c.begin(), c.end(), result.begin(), t);
    return result;
}

你可以看到它在这个实例中运行