Saya sering menggunakan konstruksi berikut untuk mengubah argumen run-time (dinamis) menjadi argumen waktu kompilasi (statis).
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.
}
}
Misalnya
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);
}
Sejauh ini bagus. Tapi sekarang saya punya argumen template
lain dan ingin juga blah()
memiliki argumen template
yang sama. Artinya, secara konseptual saya ingin
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);
}
tapi, tentu saja, hal itu tidak diperbolehkan (sebuah template
dalam lingkup blok dalam fungsi blah()
). Jadi, apa solusi yang tepat?
Perhatikan bahwa saya dapat memasukkan semuanya ke dalam templat kelas tambahan
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); }
Tapi itu kikuk dan tidak memuaskan. Apakah ada solusi alternatif atau lebih baik? Saya mencoba ini:
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); }
}
tetapi gcc (5.1.0) mengeluh bahwa S::special
diurai sebagai non-tipe sementara instantiasi menghasilkan tipe ... yang salah (menurut saya): instantiasi menghasilkan template (tetap memasukkan typename
seperti yang disarankan tidak membantu). Jadi, apa yang salah dan/atau bagaimana cara melakukannya dengan benar/lebih baik?
specialize
danspecialise
? Ini terlihat membingungkan bagi saya. - person KompjoeFriek   schedule 06.01.2016