C++ 在函数模板中调用模板化方法的包扩展
上下文:当从模板化函数调用模板化类的模板化方法时,参数包传递(甚至不是一个模糊的扩展规则),以上所有操作都涉及非类型变量参数 Q1:什么样的语法可以让下面的代码编译(希望可以按预期工作) 问题2:为了更好地了解这个C++ 在函数模板中调用模板化方法的包扩展,c++,c++11,templates,C++,C++11,Templates,上下文:当从模板化函数调用模板化类的模板化方法时,参数包传递(甚至不是一个模糊的扩展规则),以上所有操作都涉及非类型变量参数 Q1:什么样的语法可以让下面的代码编译(希望可以按预期工作) 问题2:为了更好地了解这个[咒骂删除]包扩展,您建议我读些什么。(Alexandrescu的Variatic are funadic只做了那么多,对我一点帮助都没有。是的,我知道,没有任何帮助的风险是实际存在的) -尽管它是不可编译的(只有上面的两个错误,不要担心) 作为参考,我也在这里发布了完整的代码: #i
[咒骂删除]
包扩展,您建议我读些什么。(Alexandrescu的Variatic are funadic只做了那么多,对我一点帮助都没有。是的,我知道,没有任何帮助的风险是实际存在的)
-尽管它是不可编译的(只有上面的两个错误,不要担心)
作为参考,我也在这里发布了完整的代码:
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <functional>
template <typename T, T... categories>
class Accumulator {
static const std::unordered_set<T> catset;
std::unordered_map<T, std::vector<bool>> marks_;
std::size_t size_;
void check(T val) {
if(catset.find(val)==catset.end()) {
throw std::logic_error("Unavailable cat (pick a dog)");
}
}
public:
Accumulator(std::size_t size) : marks_(), size_(size) {
for(auto c : catset) {
marks_[c]=std::vector<bool>(size, false);
}
}
std::size_t size() const {
return this->size_;
}
void clear() {
for(auto kvit : this->marks_) {
kvit.second.clear(); // sets the size to 0
kvit.second.resize(this->size_, false); // refills to size with false
}
}
bool marked(T which, std::size_t i) const {
// later we may go with DEBUG/NDEBUG and use/not-use check and at()/[]
bool ret=false;
check(which);
ret=this->marks_.find(which)->second.at(i);
return ret;
}
void mark(T which, std::size_t i, bool value=true) {
check(which);
this->marks_.find(which)->second.at(i)=value;
}
// can I go with a templated version for which? Yes I can!
template <T which> void mark(std::size_t i, bool value=true) {
check(which);
this->marks_.find(which)->second.at(i)=value;
}
// Well, maybe I can go with a variable templated version!
// *clickety-click* Well, yea, compiles and works!! Waddayaknow?!
using map_o_prefix_sums=std::unordered_map<T, std::vector<std::size_t>>;
template <T... which>
void prepare_prefix_sums(map_o_prefix_sums& cumulativeCounts) {
cumulativeCounts.clear();
// d'oh...!!! for(auto c : which...) {
constexpr T cats[]={ which... };
for(auto c : cats) {
check(c);
const std::vector<bool>& ticks=this->marks_[c]; // source
cumulativeCounts[c]=std::vector<std::size_t>(); // destinations
std::vector<std::size_t>& counts=cumulativeCounts[c];
counts.reserve(this->size_);
std::size_t sumSoFar=0;
for(bool tick : ticks) {
if(tick) {
sumSoFar++;
}
counts.push_back(sumSoFar);
}
}
}
};
template <typename T, T...cats>
const std::unordered_set<T> Accumulator<T, cats...>::catset={cats...};
template<
typename T, typename ProcR,
T... which,
bool maxesInclusive=false,
T... available
>
void process_ranged_queries(
const std::vector<std::size_t>& mins, const std::vector<std::size_t>& maxes,
const Accumulator<T, available...>& src,
std::function<ProcR(std::unordered_map<T,std::size_t>)> processor,
std::vector<ProcR>& results
) {
const std::size_t rangeLen=std::min(mins.size(), maxes.size());
if(rangeLen>0){
const std::size_t srcLen=src.size();
results.clear();
results.reserve(rangeLen);
typename decltype(src)::map_o_prefix_sums prefixSums;
src.prepare_prefix_sums<which...>(prefixSums); // OOOPPPSssshhh! Why? How???
// etc
}
}
int main() {
std::string s="GATACA";
std::size_t len=s.length();
Accumulator<char, 'A', 'C', 'T', 'G'> sumer(s.length());
for(std::size_t i=0; i<len; i++) {
sumer.mark(s[i], i);
}
sumer.clear();
for(std::size_t i=0; i<len; i++) {
switch(s[i]) {
case 'A':
case 'a':
sumer.mark<'A'>(i);
break;
case 'G':
case 'g':
sumer.mark<'G'>(i);
break;
case 'T':
case 't':
sumer.mark<'C'>(i);
break;
case 'C':
case 'c':
sumer.mark<'C'>(i);
break;
default:
break;
}
}
decltype(sumer)::map_o_prefix_sums resultsHere;
sumer.prepare_prefix_sums<'A', 'C'>(resultsHere); // works well here, the pack is fully specified
return 0;
}
#包括
#包括
#包括
#包括
模板
类累加器{
静态常数std::无序集合catset;
标准::无序的地图标记;
标准:尺寸;
无效支票(T val){
if(catset.find(val)=catset.end()){
抛出std::逻辑_错误(“不可用的猫(选狗)”;
}
}
公众:
累加器(std::size\u t size):标记号号号号号号号号号(),大小号号(size){
用于(自动c:catset){
标记_c]=std::vector(大小,假);
}
}
std::size\u t size()常量{
返回此->大小;
}
无效清除(){
用于(自动kvit:此->标记){
kvit.second.clear();//将大小设置为0
kvit.second.resize(this->size,false);//用false重新填充到size
}
}
布尔标记(T,标准::尺寸)常数{
//稍后我们将使用DEBUG/NDEBUG并使用/不使用check和at()/[]
bool-ret=假;
检查(哪个);
ret=this->marks_u.find(which)->second.at(i);
返回ret;
}
无效标记(其中,标准::大小\u T i,布尔值=真){
检查(哪个);
这个->标记_u.find(which)->second.at(i)=值;
}
//我可以使用模板版本吗?是的,我可以!
模板无效标记(标准::大小,布尔值=真){
检查(哪个);
这个->标记_u.find(which)->second.at(i)=值;
}
//好吧,也许我可以用一个变量模板版本!
//*clickety click*嗯,是的,编译并工作!!Waddayaknow?!
使用map\u o\u prefix\u sums=std::unordered\u map;
模板
无效准备前缀和(映射前缀和和累积计数){
cumulativeCounts.clear();
//d'oh…!!!对于(自动c:哪个…){
constexpr T cats[]={which…};
用于(自动c:猫){
检查(c);
const std::vector&ticks=this->marks_[c];//源
cumulativeCounts[c]=std::vector();//目的地
标准::向量和计数=累积计数[c];
计数。保留(此->大小);
标准:尺寸总和=0;
用于(布尔勾号:勾号){
如果(勾选){
sumSoFar++;
}
计数。推回(sumSoFar);
}
}
}
};
模板
常量std::无序集合累加器::catset={cats…};
模板<
类型名T,类型名PRORC,
T…这,
bool maxenclusive=false,
T…可用
>
无效进程\u范围\u查询(
常量标准::向量和分钟,常量标准::向量和最大值,
常量累加器和src,
函数处理器,
向量与结果
) {
常量std::size\u t rangeLen=std::min(mins.size(),maxes.size());
如果(范围>0){
常量std::size\u t srcLen=src.size();
结果:清晰();
结果:储备量(rangeLen);
typename decltype(src)::映射前缀和前缀;
src.prepare_prefix_sums(prefixSums);//oooppssshh!为什么?如何???
//等
}
}
int main(){
std::string s=“GATACA”;
标准::尺寸长度=标准长度();
蓄能器油箱(s.长度());
对于(std::size_t i=0;i您需要使用template
关键字作为依赖模板函数
src.template prepare_prefix_sums<which...>(prefixSums); // OOOPPPSssshhh! Why? How???
src.template prepare_prefix_sums(prefixSums);//oooppssshh!为什么?如何???
您可以查看问题及其答案以获得更详细的解释。对于依赖模板函数,您需要使用模板
关键字
src.template prepare_prefix_sums<which...>(prefixSums); // OOOPPPSssshhh! Why? How???
src.template prepare_prefix_sums(prefixSums);//oooppssshh!为什么?如何???
您可以查看问题及其答案,以获得更详细的解释。谢谢您提供的解决方案和参考谢谢您提供的解决方案和参考
src.template prepare_prefix_sums<which...>(prefixSums); // OOOPPPSssshhh! Why? How???