专门化模板模板参数的麻烦
trouble with specialising template template parameters
我经常使用以下结构将 运行 时间(动态)参数转换为编译时(静态)参数
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()
的块范围内)。 那么正确的解法是什么?
请注意,我可以将所有内容放在辅助 class 模板中
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
被解析为非类型,而实例化产生一个类型......这是错误的(我认为):实例化产生 template(无论如何按照建议插入 typename
没有帮助)。 怎么了and/or怎么办correct/better?
要添加的关键字不是 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);
}
我经常使用以下结构将 运行 时间(动态)参数转换为编译时(静态)参数
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()
的块范围内)。 那么正确的解法是什么?
请注意,我可以将所有内容放在辅助 class 模板中
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
被解析为非类型,而实例化产生一个类型......这是错误的(我认为):实例化产生 template(无论如何按照建议插入 typename
没有帮助)。 怎么了and/or怎么办correct/better?
要添加的关键字不是 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);
}