【问题标题】:trouble with specialising template template parameters专门化模板模板参数的麻烦
【发布时间】:2016-01-06 17:24:44
【问题描述】:

我经常使用以下构造将运行时(动态)参数转换为编译时(静态)参数

namespace Foo {
  enum struct option { A,B,C,D,E,F };

  template<template<option> class Func, typename... Args>
  auto Switch(option opt, Args&&...args)
  -> decltype(Func<option::A>::act(std::forward<Args>(args)...))
  {
    switch(opt) {
    case option::A : return Func<option::A>::act(std::forward<Args>(args)...);
    case option::B : return Func<option::B>::act(std::forward<Args>(args)...);
    // etc.
  }
}

例如

template<Foo::option>
void compile_time(std::string const&);         // given

namespace {
  template<Foo::option Opt>
  struct Helper {
    static void act(std::string const&str) { compile_time<Opt>(str); }
  };
}

void run_time_arg(Foo::option opt, std::string const&str)
{
  Switch<CompileTimeArg>(opt,str);
}

到目前为止一切顺利。但现在我有另一个 template 参数并且还希望 blah() 有相同的 template 参数。也就是说,从概念上讲,我想

template<int, Foo::option>
void compile_time(std::string const&);         // given

namespace {
  template<int Bar, Foo::option Opt>
  struct Helper {
    static void act(std::string const&str) { compile_time<Bar,Opt>(str); }
  };
}

template<int Bar>
void blah(Foo::option opt, std::string const&str)
{
  template<Foo::option Opt> using BarHelper = Helper<Bar,Opt>;
  Switch<BarHelper>(opt, str);
}

但是,当然,这是不允许的(template 在函数 blah() 的块范围内)。 那么正确的解决方案是什么?

请注意,我可以将所有内容放在辅助类模板中

namespace {
  template<int Bar>
  struct Auxiliary
  {
    template<Foo::option Opt> using BarHelper = Helper<Bar,Opt>;
    static void blah(Foo::option opt, std::string const&str)
    { Switch<BarHelper>(opt, str); }
  };
}

template<int Bar>
void blah(Foo::option opt, std::string const&str)
{ Auxiliary<Bar>::blah(opt, str); }

但这很笨拙且令人不满意。 是否有替代或更好的解决方案? 我试过这个:

template<typename X, typename Y, X x, template<X,Y> class C>
struct specialise {
  template<Y y> using special = C<x,y>;
};

template<int Bar>
void blah(Foo::option opt, std::string const&str)
{
  using Aux = specialise<int, Foo::option, Bar, Helper>
  Switch<Aux::special>(opt, str); }
}

但是 gcc (5.1.0) 抱怨 S::special 被解析为非类型,而实例化产生一个类型......这是错误的(我认为):实例化产生一个 模板 (无论如何,按照建议插入typename 无济于事)。 那么出了什么问题和/或如何正确/更好地做到这一点?

【问题讨论】:

  • 您是否知道您正在使用specializespecialise?我看起来很困惑。
  • @KompjoeFriek 解决了这个问题。
  • 只是出于好奇,我想知道这个是否与stackoverflow.com/questions/25202250/…有关?
  • @user2672165 在某种意义上是的,但不是直接的。

标签: c++ templates template-templates


【解决方案1】:

要添加的关键字不是typename,因为它不是类型,而是template

所以,调用应该是

template<int Bar>
void blah(Foo::option opt, std::string const& str)
{
    using Aux = specialise<int, Foo::option, Bar, Helper>
    Switch<Aux::template special>(foo, ptr, str);
}

Live Demo

【讨论】:

  • 正确。我自己已经弄清楚了,而...感谢编辑-您显然已经尝试过了!我只见过template 关键字后面跟&lt;&gt; 的这种用法,例如ptr-&gt;template func&lt;0&gt;().
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多