2016-01-06 96 views
0

我經常使用下面的結構轉換運行時(動態)參數爲編譯時(靜態)參數麻煩專業模板模板參數

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建議不幫)。 那麼有什麼不對?和/或如何做到這一點正確/更好?

+0

你知道你正在使用'specialize'和'specialise'?它讓我感到困惑。 – KompjoeFriek

+0

@KompjoeFriek修正了這個問題。 – Walter

+0

只是好奇我不知道這一個是相關http://stackoverflow.com/questions/25202250/c-template-instantiation-avoiding-long-switches? – user2672165

回答

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

+0

正確。我自己想到了這一點,意思是......而編輯是thx--你顯然已經嘗試過了!我只見過''''這個'template'關鍵字的用法,例如後面跟'<>', ''ptr-> template func <0>()'。 – Walter