C++ 函数指针名称在函数模板中查找

C++ function pointers name lookup inside function template

我试图理解名称查找和参数依赖性 lookup.I 创建了一个小示例。

已编辑:

https://godbolt.org/g/rMWUbe

#include <iostream>

void g(const int*) {}

template <typename T>
struct TypeResolution;

template <typename T>
struct TypeResolution<T&> {
    typedef const T* type;
    static constexpr void (*func_ptr)(TypeResolution::type) = g;
    static constexpr void *func_ptr_void = (void*)func_ptr;
};

template <typename T>
struct TypeResolution {
    typedef const T* type;
    static constexpr void (*func_ptr)(TypeResolution::type) = g;
    static constexpr void *func_ptr_void = (void*)func_ptr;
};

void foo_impl(void *[], void *[]) {
   //Some work here, that will be in a different file or library
}

template <typename... ARGS>
void foo(ARGS && ... args) {
   void *func_ptrs[] = { TypeResolution<ARGS>::func_ptr_void... };
   void *args_ptrs[] = {(void*)&args...};
   foo_impl(func_ptrs, args_ptrs);
}

struct MyClass {};
void g(const MyClass*) {}

int main(int argc, char* argv[]) {
   int i = 1;
   foo(i);

   int j = 2;
   foo(i, j);

   MyClass c;
   foo(c); //This fails.
}

所以我的问题是,为什么它不能编译?或者更简单地说,为什么在 TypeResolution 中查找 g 是在声明 class 时发生的,而不是在实例化时发生的?正如我在 main 函数中预期的那样,然后查看函数 void g(const MyClass*)

我想要获得的是能够为不同的不同类型调用不同的函数,而不需要转发声明它们。

我在 Ubuntu 16.04

上使用 g++ 5.4.0
template <typename T>
void foo(T t) {
   void(*f)(T) = +[](T x){ return g(std::forward<T>(x)); };
   f(t); //This compiles
   g(t); //This compiles
}

这可能就是您想要的。请注意,参数在 f 内移动了一次,这对于基本类型来说应该无关紧要。

template <class T>
struct TypeResolution;

template <class T>
struct TypeResolution<T&>:TypeResolution<T> {};

template <class T>
struct TypeResolution {
  typedef const T* type;
  static constexpr void (*func_ptr)(type) = +[](type x){ return g(x); };
  static constexpr void *func_ptr_void = (void*)func_ptr;
};

constexpr 表达式中需要 because you cannot use lambdas in or

在以前的 C++ 版本中,我们可以这样做:

template <class T>
struct TypeResolution {
  typedef const T* type;
  static void invoke_g(type t) { g( t ); }
  static constexpr void (*func_ptr)(type) = invoke_g;
  static constexpr void *func_ptr_void = (void*)func_ptr;
};

基于 Yakk 的回答和 n4487 我设法实现了一个我设法用 c++14 编译的解决方案。

https://godbolt.org/g/BRee4u

#include <iostream>
#include <type_traits>
#include <string>

void g(int*) {}

template <typename T>
struct TypeResolution;

template <typename T>
struct TypeResolution<T&> {
    struct Inner {
        static constexpr void foo(T* t) { g(t); }
    };
    static constexpr void *func_ptr_void = (void*)Inner::foo;
};

template <typename T>
struct TypeResolution {
    struct Inner {
        static constexpr void foo(T* t) { g(t); }
    };
    static constexpr void *func_ptr_void = (void*)Inner::foo;
};

void foo_impl(void *func_args[], void *data_args[]) {
    //Some work here, that will be in a different file or library
}

template <typename... ARGS>
void foo(ARGS && ... args) {
    void *func_ptrs[] = { TypeResolution<ARGS>::func_ptr_void... };
    void *args_ptrs[] = {(void*)&args...};
    foo_impl(func_ptrs, args_ptrs);
}

struct MyClass {};
void g(const MyClass*) {}

int main(int argc, char* argv[]) {
    int i = 1;
    foo(i);

    MyClass c;
    foo(c);
}