Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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
Templates 元组和向量上递归的非void函数模板_Templates_C++11_Stdvector_Stdtuple - Fatal编程技术网

Templates 元组和向量上递归的非void函数模板

Templates 元组和向量上递归的非void函数模板,templates,c++11,stdvector,stdtuple,Templates,C++11,Stdvector,Stdtuple,我已经做了一个函数来计算一个数字的正弦。如果输入类型为std::is_floating_point,则返回输入类型。但是对于std::is_integral,它返回一个双精度 template<class T , typename std::enable_if<std::is_integral<T>::value>::type* = nullptr > double mysin(const T& t) // note, function signatu

我已经做了一个函数来计算一个数字的正弦。如果输入类型为
std::is_floating_point
,则返回输入类型。但是对于
std::is_integral
,它返回一个
双精度

template<class T , typename std::enable_if<std::is_integral<T>::value>::type* = nullptr >
double mysin(const T& t) // note, function signature is unmodified
{
    double a = t;
    return std::sin(a);
}

template<class T , typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr >
T mysin(const T& t) // note, function signature is unmodified
{
    return std::sin(t);
}
在大多数关于
tuple
模板的示例中,函数要么没有返回值,要么返回累积值,要么与输入具有相同的返回类型

我对这些主题做了很多实验(其中包括): ,

最后一个特别有用。我已经为
tuple
s工作了,但是对于递归
tuple
tuple
s中的
tuple
s)不起作用

最终(如果可能的话),我必须使用gcc 4.9.2制作一个
mycos
mytan
myasin
,等等

**编辑:**这是我在雅克的建议后提出的,还有一些调整:

#include <utility>
#include <vector>
#include <memory>
#include <typeinfo> // used for typeid
#include <tuple>
#include <cstdlib> // for math functions?
#include <cmath> // for math functions
#include <type_traits> // for std::enable_if

template<class T , typename std::enable_if<std::is_integral<T>::value>::type* = nullptr >
double mysin(const T& t) { // note, function signature is unmodified
    double a = t;
    return std::sin(a);
// printing a debug string here will
// print tuple elements reversed!!
}


template<class T , typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr >
T mysin(const T& t) {// note, function signature is unmodified
// printing a debug string here will
// print tuple elements reversed!!
    return std::sin(t);
}

struct sine_t {
    template<class T>
    auto operator()(T&&t)const->
        decltype(mysin(std::declval<T>())) {
            return mysin(std::forward<T>(t));
            }
};

template<class F>
struct vectorize {
    template<class T,
        class R=std::vector< std::result_of_t< vectorize<F>(T const&) > >
    >
        R operator()( std::vector<T> const& v ) const {
            R ret;
            ret.reserve(v.size());
            for( auto const& e : v ) {
                ret.push_back( vectorize<F>{}(e) );
                }
        return ret;
        }

    template<
        class X,
        class R=std::result_of_t< F(X const&) >
    >
        R operator()( X const& x ) const {
            return F{}(x);
            }   

    template<
        class R, 
        class... Ts, 
        size_t... Is
    >
    R tup_help( std::index_sequence<Is...>, std::tuple<Ts...> const& t ) const {
        return std::make_tuple( vectorize<F>{}(std::get<Is>(t))... );
        }

    template<
        class... Ts,
        class R=std::tuple< std::result_of_t< vectorize<F>(Ts const&) >... >
    >
    R operator()( std::tuple<Ts...> const& t ) const {
        return tup_help<R>( std::index_sequence_for<Ts...>{}, t );
        }

    };

//+++++++++++++++++++++++++++++++++++++++++

int main() {
    std::vector<int> a = {1 ,2};
    std::tuple<int, double, int, double> b (42, -3.14, 42, -3.14);

    auto c = vectorize<sine_t>()(a);
    auto d = vectorize<sine_t>()(b);

    std::vector<std::tuple<int, int> > e {std::make_tuple(1 ,2)};
    //This does not not work:
    //auto f = vectorize<sine_t>()(e);

    //This works:
    std::tuple<std::vector<int> > g ( a );
    auto f = vectorize<sine_t>()(g);

    return 0;
}
#包括
#包括
#包括
#include//用于typeid
#包括
#包含//用于数学函数?
#包含//用于数学函数
#包含//用于std::如果
模板
double mysin(const T&T){//注意,函数签名是未修改的
双a=t;
返回标准::sin(a);
//在这里打印调试字符串将
//反向打印元组元素!!
}
模板
T mysin(const T&T){//注意,函数签名是未修改的
//在这里打印调试字符串将
//反向打印元组元素!!
返回std::sin(t);
}
结构正弦{
模板
自动运算符()(T&&T)常量->
decltype(mysin(std::declval())){
返回mysin(std::forward(t));
}
};
模板
结构矢量化{
模板>
>
R运算符()(std::vector const&v)const{
R-ret;
净储备(v.大小());
用于(自动施工和设备:v){
ret.push_back(向量化{}(e));
}
返回ret;
}
模板<
X类,
类R=std::t的结果
>
R运算符()(X常量和X)常量{
返回F{}(x);
}   
模板<
R类,
类…Ts,
尺寸是
>
R tup\u help(std::index\u序列,std::tuple const&t)const{
返回std::make_tuple(向量化{}(std::get(t))…);
}
模板<
类…Ts,
类R=std::tuple…>
>
R运算符()(std::tuple const&t)const{
返回tup_help(std::index_sequence_for{},t);
}
};
//+++++++++++++++++++++++++++++++++++++++++
int main(){
向量a={1,2};
std::元组b(42,-3.14,42,-3.14);
自动c=矢量化()(a);
自动d=矢量化()(b);
std::vector e{std::make_tuple(1,2)};
//这不起作用:
//自动f=矢量化()(e);
//这项工作:
std::元组g(a);
自动f=矢量化()(g);
返回0;
}

这很有效。需要c++14。

首先是重载集对象。这很有用,因为它允许我们将整个重载集作为单个对象传递:

struct sine_t {
  template<class T>
  auto operator()(T&&t)const->
  decltype(mysin(std::declval<T>()))
  { return mysin(std::forward<T>(t)); }
};
现在我们支持
std::vector

为了支持元组,我们添加了2个函数。第一个有这个签名:

  template<
    class... Ts,
    class R=std::tuple< std::result_of_t< vectorize<F>(Ts const&) >... >
  >
  R operator()( std::tuple<Ts...> const& t ) const
模板<
类。。。Ts,
类R=std::tuple…>
>
R运算符()(std::tuple const&t)const
这让我们得到了回报值(战斗的一半)。要实际执行映射,请使用索引技巧:

  template<
    class R,
    class... Ts,
    size_t... Is
  >
  R tup_help( std::index_sequence<Is...>, std::tuple<Ts...> const& t ) const
  {
    return std::make_tuple( vectorize<F>{}(std::get<Is>(t))... );
  }
  template<
    class... Ts,
    class R=std::tuple< std::result_of_t< vectorize<F>(Ts const&) >... >
  >
  R operator()( std::tuple<Ts...> const& t ) const {
    return tup_help<R>( std::index_sequence_for<Ts...>{}, t );
  }
模板<
R类,
类。。。Ts,
大小\u t。。。是
>
R tup\u help(std::index\u序列,std::tuple const&t)const
{
返回std::make_tuple(向量化{}(std::get(t))…);
}
模板<
类。。。Ts,
类R=std::tuple…>
>
R运算符()(std::tuple const&t)const{
返回tup_help(std::index_sequence_for{},t);
}
用于
std::array
和原始C数组的类似代码应该可以工作(自然地将原始C数组转换为
std::array

std::index_sequence
etc是C++14,但很容易编写一个版本,在C++11中支持100个元素。(支持大型阵列的版本需要更多的工作)。别名(以及任何类似的)的
result\u也是C++14,但是别名很容易用C++11编写,或者您可以只使用
typename std::result\u of::type
verbose explosion

最后,您将{}
矢量化并传入任何内容


如果您想要函数而不是函数对象,只需让它将工作委托给
vectorize

@wiebe是的,
vectorize{}(e)
我将在今天晚些时候尝试修复中断调用的打字错误:调试SFINAE错误有时很棘手。其思想是,
sine\u t
调用一组自由函数的重载是有用的。你可以给它一个不同的名字(
my\u sinu\u element
),把
my\u sine
写成调用
vectorize{}(t)
。不知道为什么我今天删除了我的评论后才看到你的评论。。。不管怎样,你让我达到了95%,另外5%是一次很好的学习经历。注意std::index_序列后面的“s”。这是唯一的错误,否则你的代码是完美的,我只是不理解向量化{}(t)语法。它比矢量化()更好吗?谢谢。@Wiebe它清楚地表明我正在构造一个对象,而不是调用一个函数。就这样。必须阅读第7项,有效的现代C++。这是关于()和{}。仍在第3项。。。顺便说一下,它不适用于元组向量(向量>)。编译器说没有模板。元组、向量和积分工作正常。向量元组也可以。好的,修复了元组向量问题。类R=std::vector>应该是类R=std::vector>,否则它不会递归向量类型。
  template<
    class T,
    class R=std::vector< std::result_of_t< vectorize<F>(T const&) > >
  >
  R operator()( std::vector<T> const& v ) const {
    R ret;
    ret.reserve(v.size());
    for( auto const& e : v ) {
      ret.push_back( vectorize<F>{}(e) );
    }
    return ret;
  }
  template<
    class... Ts,
    class R=std::tuple< std::result_of_t< vectorize<F>(Ts const&) >... >
  >
  R operator()( std::tuple<Ts...> const& t ) const
  template<
    class R,
    class... Ts,
    size_t... Is
  >
  R tup_help( std::index_sequence<Is...>, std::tuple<Ts...> const& t ) const
  {
    return std::make_tuple( vectorize<F>{}(std::get<Is>(t))... );
  }
  template<
    class... Ts,
    class R=std::tuple< std::result_of_t< vectorize<F>(Ts const&) >... >
  >
  R operator()( std::tuple<Ts...> const& t ) const {
    return tup_help<R>( std::index_sequence_for<Ts...>{}, t );
  }