可以将在运行时确定的模板参数传递给specialize函数

时间:2015-08-23 02:45:22

标签: c++ templates specialization

道歉,我会自己尝试一下,但我暂时不会在电脑附近,想知道下面的内容是否可行。我想在运行时确定模板参数,并最终将其传递给专门的函数。如果不是最有效的方法是什么?

class validate
{
    public:
            template<int x>  
            bool valid();
};


template<> 
bool validate:valid<0>() { return false;}

template<>
bool validate:valid<5>() { return true;}



template <int p>
class Ctx
{
      public:
            bool run() { return _val.template valid<p>();}

    validate _val;   
}

class Handler 
{
     public:

           Handler(const string& str) 
           {
                if(str=="blue")
                  _ctx = new Ctx<1>();
                else if("str = "red")
                  _ctx = new Ctx<5>();
                else
                   _ctx = new Ctx<0>();

           }

           Ctx<int>* getCtx() { return _ctx;}

      private:

           Ctx<int>* _ctx;

};

void main()
{
     //read string from keyboard prompt.. cin >> value;
     Handler h(value);
     Ctx<int>* ctx = h.getCtx();
     bool v = ctx->run();
}

扩展这个,因为我将知道输入值的范围,我可以做类似下面的事情(改编自stackoverflow上的另一个问题),实质上扩展所有值的Ctx模板并使用和数组进行查找?问题是将模板

bool run(),为每个专门的运行函数工作吗?

template <int p>
class Ctx
{
      public:
            template<p> 
            bool run();

}
template<>   //will these work?
bool Ctx<int>::run<5>() { return true; }

template<>   //will these work?
bool Ctx<int>::run<3>() { return false; }


template<int N, int... Ns>
struct ctx_table : ctx_table<N -1, N-1, ,Ns...> {};

template<int... Ns>
struct ctx_table<0,Ns...>
{ 
   static constexpr void (*ctxs<int>[]() = {Ctx<Ns>...};
};

template <int... Ns>
constexpr void (*ctx_table<0,Ns...>::ctxs<int>[sizeof...(ns)]) ();

int main()
{
    cint >> value;
    int val = atoi(value);
    if(val >100) 
        return 0;
    //can I do this?   
    ctx_table<100>::ctxs[val].run();
}

2 个答案:

答案 0 :(得分:1)

您正在尝试在运行时使用编译时构造。那是不可能的。你真正想要的是多态类或简单函数。

P.S。
您无法专门化成员函数模板,因此示例的第一部分(即使语法正确)也不正确。

使用独立的功能将是最好,最有效的想法:

template<int N>
struct is_valid: public std::false_type{};

template<>
struct is_valid<5>: public std::true_type{};

auto is_valid_str(const std::string &str) -> bool{
    if(str == "blue")
        return is_valid<1>::value;
    else if(str == "red")
        return is_valid<5>::value;
    else
        return false;
}

auto main() -> int{
    std::string input;
    std::cin >> input;
    std::cout << "valid: " << std::boolalpha << is_valid_str(input) << std::endl;
}

但是如果您需要动态调度(您目前没有),请使用抽象基类:

class base{
    public:
        virtual ~base(){}
        virtual auto run() -> void = 0;
};

template<int N>
class derived: public base{
    public:
        auto run(){ throw std::runtime_error("bad input"); }
};

template<>
class derived<1>: public base{
    public:
        auto run(){ std::cout << "doing work for<1>..." << std::endl; }
};

template<>
class derived<5>: public base{
    public:
        auto run(){ std::cout << "doing work for <5>..." << std::endl; }
};

然后把它们放在一起:

auto get_dispatch(const std::string &str) -> std::unique_ptr<base>{
    if(str == "blue")
        return new derived<1>{};
    else if(str == "red")
        return new derived<5>{};
    else
        return new derived<0>{};
}

auto main() -> int{
    std::string input;
    std::cin >> input;
    auto dispatch = get_dispatch(input);
    dispatch->run();
}

答案 1 :(得分:0)

我不相信C ++模板以这种方式工作。对Ctx类的构造函数的调用将在编译时解析。因此,您可以在运行时调用所需的正确函数。但总的来说,您不能依赖模板进行运行时操作。模板在代码运行时解析

一个简单的解决方案是获取函数的键映射,并根据传递的参数在运行时解析函数调用。