Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.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

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
C++ C++;模板排序_C++_Templates_C++11_Variadic Templates - Fatal编程技术网

C++ C++;模板排序

C++ C++;模板排序,c++,templates,c++11,variadic-templates,C++,Templates,C++11,Variadic Templates,我正在寻找模板代码来对模板参数进行排序,例如: template <typename T, typename ... Args> list<T> sort(T first, Args ... rest) (事实上,我计划使用一个“all_different”,它将对重复项进行排序和删除,以评估4个值varA、varB、varC、varD是否都不同) 如果您想对函数参数进行排序,那么在任何地方都可以编写这种函数?这是非常容易实现的。只需从参数中构建一个向量(或者一个std

我正在寻找模板代码来对模板参数进行排序,例如:

template <typename T, typename ... Args>
list<T> sort(T first, Args ... rest)
(事实上,我计划使用一个“all_different”,它将对重复项进行排序和删除,以评估4个值varA、varB、varC、varD是否都不同)


如果您想对函数参数进行排序,那么在任何地方都可以编写这种函数?

这是非常容易实现的。只需从参数中构建一个向量(或者一个
std::list
,如果出于任何原因需要使用它),并对其进行排序

template <typename T, typename ... Args, typename T_d = std::decay_t<T>>
std::vector<T_d> sort(T&& first, Args&&... rest){
    // optionally static assert that all of decay_t<Args>... are the same as T_d

    // build the vector
    std::vector<T_d> ret;
    ret.reserve(1 + sizeof...(Args));
    ret.push_back(std::forward<T>(first));
    using expander = int[];
    (void) expander{0, (ret.push_back(std::forward<Args>(rest)), 0)...};

    // now sort it
    std::sort(ret.begin(), ret.end());
    return ret;
}
但这会导致每个元素增加一个副本(并且不适用于仅移动类型),因为您无法从
std::initializer\u列表中移动,这很简单:

template <typename T, typename... Args>
list<T> sort(const T& first, Args... args)
{
    list<T> result{first, args...};
    result.sort();
    return result;
}
模板
列表排序(常量T&first,参数…参数)
{
列出结果{first,args…};
result.sort();
返回结果;
}

一次只做一件事:

template<class R>
R sort_the_range( R&& r ) {
  using std::begin; using std::end;
  std::sort( begin(r), end(r) );
  return std::forward<R>(r);
}
模板
R排序\u范围(R&R){
使用std::begin;使用std::end;
排序(开始(r),结束(r));
返回std::向前(r);
}
一些元编程:(hana风格)

模板结构标记{using type=T;};
模板结构类型{using type=types;};
templateusing type\u t=typename标记::type;
模板::类型
>
constexpr标记类型_from(标记,Ts..){return{};}
模板
constexpr标记类型_from(标记,标记,Ts…){return{};}
模板
使用type_from_t=type_t
现在,一个生成向量的函数。您可以为向量传入一个类型,或者让它从第一个参数推断出您的选择:

// explicit T argument is optional:
template<class ExplicitType=void, class...Ts,
  // deduce return type:
  class R=type_from_t<ExplicitType, typename std::decay<Ts>::type...>
>
std::vector<R> make_vector( Ts&&... ts ) {
  // block explicit conversions:
  using test = decltype(std::array<R, sizeof...(Ts)>{{ std::declval<Ts>()... }});
  (void)tag<test>{}; // block warnings
  // make our vector, and size it right:
  std::vector<R> retval;
  retval.reserve( sizeof...(ts) );
  // populate the vector:
  (void)std::initializer_list<int>{0,((
    retval.emplace_back(std::forward<Ts>(ts))
  ),void(),0)...};
  return retval;
}
//显式T参数是可选的:
模板
标准::向量生成向量(Ts&&…Ts){
//块显式转换:
使用test=decltype(std::array{{{std::declval()…}});
(void)标记{};//阻止警告
//制作我们的向量,并调整其大小:
std::向量检索;
回收储备(规模…(ts));
//填充向量:
(void)std::初始值设定项列表{0((
后装炮台(标准:前装炮台)
),void(),0)…};
返回返回;
}
和缝合:

template<class T=void, class...Ts>
auto make_sorted_vector(Ts&&...ts)
->decltype( make_vector<T>(std::forward<Ts>(ts)...) )
{
  return sort_the_range(
    make_vector<T>( std::forward<Ts>(ts)... )
  );
}
模板
自动生成排序向量(Ts&…Ts)
->decltype(生成向量(std::forward(ts)…)
{
返回排序范围(
生成向量(std::forward(ts)…)
);
}

)

有什么理由不在这里使用初始值设定项列表,比如说,有一个排序例程,比如
sort({varA,varB,varC,varD})
?您实际上没有对模板参数(
T,Args…
)进行排序,对吗?您想先对
进行排序,然后再对其进行排序…
@将强制复制的templatetypedef。如果正确地添加了转发引用,则不必添加此副本。我没有否决投票,但这将产生额外副本。您仍然需要从初始值设定项列表中添加一份副本:)@t.C.Point。哇,这段代码在C++14和C++1z中变得更清晰了。C++14允许您将工作打包到自动lambda中。C++1z为您提供了折叠表达式。让函数只接受“Args&&…”并使用可变类型函数获得t不是更清楚吗?这将消除“保留”的“1+”和单独的“推回”。简单类型函数实现:模板结构头{static_assert(sizeof…(Args)!=0,“没有为'Head'指定类型);};模板结构头{using type=T;};什么,没有
安置
<代码>向后推
会给你一份不必要的副本@在类型不匹配的问题上胡说八道?就这样吧(这将是一个行动)。我不想允许显式转换。@t.C.说得好。添加一个“显式转换将生成错误”
,使用no_explicit=std::tuple?@T.C.不在我的测试中:(将
好的
替换为
坏的
,您会得到一个转换错误,它不会调用
显式的
转换)。注意,我正在创建一个一次性元组类型,而不是元组:该行的点是
R{Ts}
构造,它应该是非显式的。
template<class T> struct tag{using type=T;};
template<class...> struct types{using type=types;};
template<class Tag>using type_t=typename Tag::type;

template<class Default, class...Ts,
  class=typename std::enable_if<!std::is_same<void,Default>::value>::type
>
constexpr tag<Default> type_from( tag<Default>, Ts... ) { return {}; }
template<class T0, class...Ts>
constexpr tag<T0> type_from( tag<void>, tag<T0>, Ts... ) { return {}; }

template<class Default, class...Ts>
using type_from_t = type_t< decltype( type_from( tag<Default>{}, tag<Ts>{}... ) ) >;
// explicit T argument is optional:
template<class ExplicitType=void, class...Ts,
  // deduce return type:
  class R=type_from_t<ExplicitType, typename std::decay<Ts>::type...>
>
std::vector<R> make_vector( Ts&&... ts ) {
  // block explicit conversions:
  using test = decltype(std::array<R, sizeof...(Ts)>{{ std::declval<Ts>()... }});
  (void)tag<test>{}; // block warnings
  // make our vector, and size it right:
  std::vector<R> retval;
  retval.reserve( sizeof...(ts) );
  // populate the vector:
  (void)std::initializer_list<int>{0,((
    retval.emplace_back(std::forward<Ts>(ts))
  ),void(),0)...};
  return retval;
}
template<class T=void, class...Ts>
auto make_sorted_vector(Ts&&...ts)
->decltype( make_vector<T>(std::forward<Ts>(ts)...) )
{
  return sort_the_range(
    make_vector<T>( std::forward<Ts>(ts)... )
  );
}