Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 专门化默认模板参数包_C++_C++14 - Fatal编程技术网

C++ 专门化默认模板参数包

C++ 专门化默认模板参数包,c++,c++14,C++,C++14,假设我已经为STL元组(元组,对)以及STL序列(向量,列表,deque)编写了通用映射函数。现在我想编写一个全局映射函数,在给定输入类型的情况下调用相应的特殊函数 我有一些类似于 template <typename... Ts> struct mappable { static constexpr bool is_instance = false; }; template <typename... Tuples, typename = require<all

假设我已经为STL元组(元组,对)以及STL序列(向量,列表,deque)编写了通用映射函数。现在我想编写一个全局映射函数,在给定输入类型的情况下调用相应的特殊函数

我有一些类似于

template <typename... Ts>
struct mappable {
    static constexpr bool is_instance = false;
};

template <typename... Tuples, typename = require<all<is_stl_tuple, Tuples...>::value>>
struct mappable<Tuples...> {
  template <typename Func>
  auto map(Func&& f, Tuples&&... ts) {
     return tuple::map(std::forward<Func>(f), ts...);
  }

  static constexpr bool is_instance = true;
};

template <typename... Sequences, typename = require<all<is_stl_sequence, Sequences...>::value>>
struct mappable<Sequences...> {
    template <typename Func>
    auto map(Func&& f, Sequences&&... seqs) {
        return sequence::map(std::forward<Func>(f), seqs...);
    }

    static constexpr bool is_instance = true;
};

template <typename Func, typename... Ts>
auto map(Func&& f, Ts&&... ts) {
    static_assert(mappable<Ts...>::is_instance, "Tried calling map on unsupported types. Mappable arguments must be supplied.");
    return mappable<Ts...>::map(std::forward<Func>(f), std::forward<Ts>(ts)...);
}
模板
结构可映射{
静态constexpr bool是_instance=false;
};
模板
结构可映射{
模板
自动映射(Func&&f、元组&&ts){
返回元组::映射(std::forward(f),ts…);
}
静态constexpr bool是_instance=true;
};
模板
结构可映射{
模板
自动映射(函数和函数、序列和序列){
返回序列::map(std::forward(f),seqs;
}
静态constexpr bool是_instance=true;
};
模板
自动映射(函数和函数、Ts和…Ts){
静态_断言(mappable::is_实例,“尝试在不支持的类型上调用映射。必须提供可映射参数。”);
返回可映射::映射(std::forward(f),std::forward(ts)…);
}
尽管类型检查函数很有可能是自解释的,但它定义:

// true iff Unary<Ts>::value... == true for at least one Ts
template <template <typename> class Unary, typename... Ts>
struct any;

// true iff Unary<Ts>::value... == true for all Ts
template <template <typename> class Unary, typename... Ts>
struct all;

template <bool B>
using require = typename std::enable_if<B>::type;
//true iff一元::值…==至少一个Ts为true
模板
构造任何;
//真iff一元::值…==对所有人都是如此
模板
结构全部;
模板
使用require=typename std::enable_if::type;
显然,这不会(也不会)起作用,因为我专门化了默认参数的mappable。有没有办法做到这一点?如果没有(我必须重新设计),您将如何重新设计这些功能?例如,map应该采用stl序列的任何组合,所以我关于重构的所有想法都只是将问题转移到别处

提前感谢您的帮助

编辑: 根据要求,以下是使用示例(实际上是我的测试代码)在我开始执行上述操作之前:

auto t0 = std::make_tuple(2.f, -5, 1);
auto t1 = std::make_tuple(1, 2);
auto b0 = tuple::map([] (auto v) { return v > decltype(v)(0); }, t0);
auto r0 = tuple::map([] (auto v0, auto v1) { return v0 + v1; }, t0, t1);
// b0 is tuple<bool, bool, bool>(true, false, true)
// b1 is tuple<float, int>(3.f, -3)
auto t0=std::make_tuple(2.f,-5,1);
auto t1=std::make_tuple(1,2);
auto b0=tuple::map([](auto v){return v>decltype(v)(0);},t0);
auto r0=tuple::map([](auto v0,auto v1){return v0+v1;},t0,t1);
//b0是元组(真、假、真)
//b1是元组(3.f,-3)
对于序列:

std::vector<float> s0 = {1.f, 2.f, 3.f, 0.f};
std::list<int>   s1 = {3, 0, -2};
auto r = sq::map([] (auto v0, auto v1) { return v0 + v1; }, s0, s1);
// type of r is compound type of first argument (vector here), result is
// vector<float>(4.f, 2.f, 1.f)
std::vector s0={1.f,2.f,3.f,0.f};
列表s1={3,0,-2};
auto r=sq::map([](auto v0,auto v1){return v0+v1;},s0,s1);
//r的类型是第一个参数的复合类型(这里是向量),结果是
//向量(4.f,2.f,1.f)

这些映射函数的实现是完全不同的——我上面的方法的目的是能够删除名称空间,只使用映射,让它做正确的事情。

为什么不只使用两个函数重载

template <typename Func, typename... Tuples,
    require<all<is_stl_tuple, Tuples...>>...>
auto map(Func&& f, Tuples&&... ts) {
    return tuple::map(std::forward<Func>(f), std::forward<Tuples>(ts)...);
}

template <typename Func, typename... Sequences,
    require<all<is_stl_sequence, Sequences...>>...>
auto map(Func&& f, Sequences&&... seqs) {
    return sequence::map(std::forward<Func>(f), std::forward<Sequences>(seqs)...);
}

顺便说一下,您正在滥用
转发
。它只适用于推导类型。你能给出一个用法示例吗?@KerrekSB:1。您指的是std::forward。。。和std::转发。。。我希望,我想这是完全正确的。2.编辑这个问题以给出一些例子……我会这样做:为元组编写一个重载,为对编写一个重载,为容器编写一个重载。它们都应该是模板,最后一个应该使用某种
is\u容器
trait,就像它一样。如果您愿意,您可以改进此方法以支持更精细的左值与右值对比。@KerrekSB实际上我想我的问题是如何“为元组[…]编写一个重载,为容器编写一个重载”。所有重载都将具有相同的参数(Func和XYZ…)。Yuris的回答建议我应该(我觉得有点奇怪)基于返回类型重载-尽管这会导致一些其他问题。。。编辑:我应该说得更清楚一点,当我在上面的一个类型类上尝试SFINAE时,这个问题是关于这个重载问题的更一般的问题。我得到了一个与此类似的问题,编译器调用第二个是对第一个的重新定义-你能编译这个代码吗?@RichardVock现在我是,但是我不得不重新实现一些东西。首先感谢你的工作(应该提供整个实现)。关于这个解决方案,我注意到您的返回类型是无效的。enable_if有第二个模板参数来代替它,所以理论上我可以使用decltype(xyz::map(…)来代替它,但是tuple::map(…)的返回类型依赖于std::tuple_size,所以我得到了一个编译错误。尽管如此,您的答案引导我朝着正确的方向前进,我仍然面临的问题更像是一个单独的问题;)Upvote和accept将在几分钟内完成……”将其放入返回类型在gcc 4.8.1中起作用:“因为返回类型是函数模板签名的一部分,而默认参数不是。请参阅[defns.signature.temp]@RichardVock可以将fsinae测试从返回类型中移除,请参阅编辑2。
template <bool condition>
struct require_impl {};

template <>
struct require_impl<true> {
    enum class type {};    
};

template <typename Condition>
using require = typename require_impl<Condition::value>::type;