我试图理解名称查找和参数依赖项查找。我创建了一个小例子。
编辑:
#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,而不是在实例化它时?正如我在main函数中所期望的那样,然后看到函数void g(const MyClass*)
我想要获得的是能够为不同的不同类型调用不同的函数,但无需转发声明它们。
我在Ubuntu 16.04上使用g ++ 5.4.0
答案 0 :(得分:2)
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;
};
需要c++17,因为您无法在constexpr
表达式c++14或c++11中使用lambdas。
在以前的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;
};
答案 1 :(得分:0)
根据Yakk的回答并基于n4487我设法实现了一个我用c ++ 14编译的解决方案。
#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);
}