C++ 在函数模板中调用模板化方法的包扩展

C++ 在函数模板中调用模板化方法的包扩展,c++,c++11,templates,C++,C++11,Templates,上下文:当从模板化函数调用模板化类的模板化方法时,参数包传递(甚至不是一个模糊的扩展规则),以上所有操作都涉及非类型变量参数 Q1:什么样的语法可以让下面的代码编译(希望可以按预期工作) 问题2:为了更好地了解这个[咒骂删除]包扩展,您建议我读些什么。(Alexandrescu的Variatic are funadic只做了那么多,对我一点帮助都没有。是的,我知道,没有任何帮助的风险是实际存在的) -尽管它是不可编译的(只有上面的两个错误,不要担心) 作为参考,我也在这里发布了完整的代码: #i

上下文:当从模板化函数调用模板化类的模板化方法时,参数包传递(甚至不是一个模糊的扩展规则),以上所有操作都涉及非类型变量参数

Q1:什么样的语法可以让下面的代码编译(希望可以按预期工作)

问题2:为了更好地了解这个
[咒骂删除]
包扩展,您建议我读些什么。(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???