James Franco
James Franco

Reputation: 4726

Dynamically specify which method to use based on a template type

Suppose I have a method which is simplified to this

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
    }
} 

Now I am using it as

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

Now val.second in Line A has 3 methods in it

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

Currently i am using val.second->getMethodA() with template type FirstType

is there anyway for me to specify to use getMethodB if template type is SecondType and use getMethodC if template type is ThirdType

Upvotes: 4

Views: 144

Answers (3)

Oktalist
Oktalist

Reputation: 14734

In the absence of C++17 I would probably go for something simple like this:

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>{});

In the context of your example:

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>{});
    }
}

Upvotes: 1

Johan Lundberg
Johan Lundberg

Reputation: 27068

With C++17 you can use 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();
   }
}

Upvotes: 1

eerorika
eerorika

Reputation: 238461

The simplest solution is to replace the three getMethodX member functions with a single template function template<class T> T foo::getMethod(). Then create specializations for each type, if needed.

But if that is not appropriate for the design, then you can use a wrapper function instead:

template<class T>
struct helper {};

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

Upvotes: 1

Related Questions