Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC failed with variadic template and pointer to member function

Tags:

c++

gcc

c++11

c++14

#include <memory>
#include <iostream>

class           Manager
{
public:
  Manager() {}
  virtual ~Manager() {}

  int funcA(std::shared_ptr<int> a, float b) { return *a + b; }
  int funcA(std::shared_ptr<double> a) { return *a; }
};

template <typename T, typename... Args>
auto resolver(int (Manager::*func)(std::shared_ptr<T>, Args...)) -> decltype(func) {
  return func;
}                                                                                                                                  

int main(int, char **)
{
  Manager m;
  Manager *ptr = &m;

  auto var = std::make_shared<int>(1);

  int result = (ptr->*resolver<int>(&Manager::funcA))(var, 2.0);

  std::cout << result << std::endl;

  return 0;
}

This code fail to compile with gcc but is fine with clang. (gcc 5.3.1 and 6.0.0 20151220).

Do you know if there is any solution to make it compile with gcc ? I tried with template specialization and explicit instantiation.

EDIT: gcc gives the following error:

test > g++ -std=c++11 test.cpp 
test.cpp: In function 'int main(int, char**)':
test.cpp:29:52: error: no matching function for call to 'resolver(<unresolved overloaded function type>)'
   int result = (ptr->*resolver<int>(&Manager::funcA))(var, 2.0);
                                                    ^
test.cpp:15:6: note: candidate: template<class T, class ... Args> decltype (func) resolver(int (Manager::*)(std::shared_ptr<_Tp1>, Args ...))
 auto resolver(int (Manager::*func)(std::shared_ptr<T>, Args...)) -> decltype(func) {
      ^
test.cpp:15:6: note:   template argument deduction/substitution failed:
test.cpp:29:52: note:   mismatched types 'std::shared_ptr<int>' and 'std::shared_ptr<double>'
   int result = (ptr->*resolver<int>(&Manager::funcA))(var, 2.0);
                                                    ^
test.cpp:29:52: note:   could not resolve address from overloaded function '& Manager::funcA'
test > 
like image 921
Sébastien Chapuis Avatar asked Aug 24 '26 18:08

Sébastien Chapuis


1 Answers

As a workaround, you may use

template <typename T>
struct resolver
{
    template <typename... Args>
    auto operator ()(int (Manager::*func)(std::shared_ptr<T>, Args...)) -> decltype(func) {
      return func;
    }
};

With call like

(ptr->*resolver<int>{}(&Manager::funcA))(var, 2.0);

Note the extra {} to call constructor.

like image 87
Jarod42 Avatar answered Aug 27 '26 08:08

Jarod42



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!