根据模板类型动态指定要使用的方法

时间:2016-07-23 22:49:56

标签: c++ templates c++11

假设我有一个简化为此

的方法
template<typename t,typename u>
std::shared_ptr<bar> MyClass::getFunct(std::string SomeStr)
{
    .....
    std::map<std::string,std::shared_ptr<foo> > j;
    ....
    std::shared_ptr<u> collection(new u());
    for (auto val : j){
    val.second->getMethodA() //Will return object of type t <----LINE A
    }
} 

现在我用它作为

getFunct<FirstType>("SomeString")
getFunct<SecondType>("SomeString")
getFunct<ThirdType>("SomeString")

现在是{A}行中的val.second 有三种方法

val.second->getMethodA() //returns a type of FirstType
val.second->getMethodB() //returns a type of SecondType
val.second->getMethodC() //returns a type of ThirdType

目前我正在使用  模板类型为val.second->getMethodA()

FirstType 如果模板类型为getMethodB

无论如何都要指定使用SecondType 如果模板类型为getMethodC

,请使用ThirdType

3 个答案:

答案 0 :(得分:1)

最简单的解决方案是使用单个模板函数getMethodX替换三个template<class T> T foo::getMethod()成员函数。然后根据需要为每种类型创建特化。

但如果这不适合设计,那么你可以使用包装函数:

template<class T>
struct helper {};

template<>
struct helper<FirstType> {
    static FirstType getMethod(foo& f) {
        return f.getMethodA();
    }
};
// repeat specializations for other member functions

答案 1 :(得分:1)

使用C ++ 17,您可以使用constexpr if

template<typename T>
decltype(auto) foo(Bar& bar){
   if constexpr(std::is_same_v<T,FirstType>){
       return bar.getMethodA();
   }
   if constexpr(std::is_same_v<T,SecondType>){
       return bar.getMethodB();
   }
   if constexpr(std::is_same_v<T,ThirdType>){
       return bar.getMethodC();
   }
}

答案 2 :(得分:1)

在没有C ++ 17的情况下,我可能会选择这样简单的东西:

template <typename T> struct type {};

struct select
{
    bar &b;
    decltype(auto) operator()(type<FirstType>) const { return b.getMethodA(); }
    decltype(auto) operator()(type<SecondType>) const { return b.getMethodB(); }
    decltype(auto) operator()(type<ThirdType>) const { return b.getMethodC(); }
};
select{*val.second}(type<T>{});

在您的示例中:

template <typename T> struct type {};

template<typename t,typename u>
std::shared_ptr<bar> MyClass::getFunct(std::string SomeStr)
{
    .....
    std::map<std::string,std::shared_ptr<foo> > j;
    ....
    for (auto val : j) {
        struct select {
            bar &b;
            decltype(auto) operator()(type<FirstType>) const { return b.getMethodA(); }
            decltype(auto) operator()(type<SecondType>) const { return b.getMethodB(); }
            decltype(auto) operator()(type<ThirdType>) const { return b.getMethodC(); }
        };
        select{*val.second}(type<t>{});
    }
}