user3880248
user3880248

Reputation: 73

Invoking and overloaded template function

Assuming I have 2 overloaded methods in a class shown below Please ignore the need for such a weird overloading of methods it is something I came across recently

    class A{
      public:

        //Lets call this method 1
        int GetVal(bool isCondition) const
        {
             //do something and return val
        }

        //Lets call this method 2
        template<typename T>
        int GetVal(T expression)
        {
            //do something using expression
            //and return val
        }

    };

int main()
{
    A obj;
    int val = obj.GetVal(false) << std::endl; //I want to invoke method 1
}

In the main() function, I want to invoke method1 and not method2. How can I achieve this? Thanks for reading

Upvotes: 3

Views: 73

Answers (3)

max66
max66

Reputation: 66200

In the main() function, I want to invoke method1 and not method2. How can I achieve this? Thanks for reading

And it's exactly what you get calling

obj.GetVal(false)

because false is a bool so it's an exact match for the not-template method. And when a call matches with a template method and a not template method, the not-template method (in case of exact match) is preferred.

The real problem is: how to invoke the method2 calling it with the type (bool) of the not template method (method 1) ?

The answer (a possible answer) is: add a template calling it

obj.template GetVal(false)

The following is a full working example

#include <iostream>

struct A
 {
   //Lets call this method 1
   int GetVal (bool)
    { return 1; }

   //Lets call this method 2
   template <typename T>
   int GetVal (T)
    { return 2; }
 };

int main ()
 {
   A obj;

   std::cout << obj.GetVal(false) << std::endl;           // print 1
   std::cout << obj.template GetVal(false) << std::endl;  // print 2
 }

-- EDIT --

Given that the OP precise that method 1 is const (and method 2 isn't), method 2 become the better match.

The problem can be solved modifying A as in Jarod42's answer (adding a not-const not-template method that call the const method or SFINAE disabling the template method 2 when T is bool) or as in Wanderer's answer (making const also method 2).

But if you don't wont (or if you can't) modify the class A, you can simply use static_assert() directly in main()

std::cout << static_cast<A const &>(obj).GetVal(false) << std::endl;

Upvotes: 3

Wanderer
Wanderer

Reputation: 329

I know only 2 choices

  1. Use all overloads as const

    //Lets call this method 1
    int GetVal(bool isCondition) const
    { /*do something and return val*/ }
    
    //Lets call this method 2
    template<typename T>
    int GetVal(T expression) const
    { /*do something using expression and return val*/ }
    
  2. or as non const

    //Lets call this method 1
    int GetVal(bool isCondition)
    { /*do something and return val*/ }
    
    //Lets call this method 2
    template<typename T>
    int GetVal(T expression)
    { /*do something using expression and return val*/ }
    

Then Method 1 will be invoked

   std::cout << obj.GetVal(false) << std::endl;

If you need Method 1 const use Jarod42 second example. It is wokring

template <typename T, std::enable_if_t<!std::is_same<bool, T>::value> = 0 >
int GetVal(T expression)
{ /*do something using expression and return val*/ }

Upvotes: 1

Jarod42
Jarod42

Reputation: 217135

You might add extra overload:

class A{
public:
    // Lets call this method 1
    int GetVal(bool isCondition) const { /* do something and return val */ }
    int GetVal(bool b) { return static_cast<const A&>(*this).GetVal(); }

    // Lets call this method 2
    template<typename T>
    int GetVal(T expression) { /* do something using expression and return val */ }}
};

Or use SFINAE for method2 to discard bool parameter:

class A{
public:
    // Lets call this method 1
    int GetVal(bool isCondition) const { /* do something and return val */ }

    // Lets call this method 2
    template <typename T, std::enable_if_t<!std::is_same<bool, T>::value>, int> = 0>
    int GetVal(T expression) { /* do something using expression and return val */ }}
};

Upvotes: 1

Related Questions