완벽하게 작동하는 유일한 기술은 C 콜백 내에서 호출하려는 각 멤버 함수에 대해 C 래퍼 함수를 작성하는 것입니다. 즉 :
extern "C" void Foo_x(Foo *foo)
{
foo->x();
}
extern "C" void Foo_x1(Foo *foo, int i)
{
foo->x1(i);
}
또한 암시 적으로 동일한 매개 변수를 가진 기능과 폐쇄 형의 함수 호출 연산자로 유형을 반환하는 포인터로 변환 C++ 0X의 람다 표현식을 사용할 수 있습니다. 그러나 함수 유형의 언어 연결은 "C"가 아니라 "C++"입니다.
#include <cstdlib>
#include <iostream>
using namespace std;
struct Foo
{
void x() { cout << "Foo::x()" << endl; }
void x1(int i) { cout << "Foo::x1(" << i << ")" << endl; }
};
int main()
{
typedef void (*f_t)(Foo*); // default ("C++") language linkage
typedef void (*f1_t)(Foo*, int);
Foo foo;
Foo_x(&foo);
Foo_x1(&foo, -10);
f_t fn = [] (Foo *foo) {
foo->x();
};
fn(&foo);
f1_t fn1 = [] (Foo *foo, int i) {
foo->x1(i);
};
fn1(&foo, 314);
return EXIT_SUCCESS;
}
노트는 C++ 표준의 섹션 5.2.2, 함수 호출, 진술한다 :
가 그 기능 유형의 언어 결합 상이한 언어 결합을 갖는 식으로 함수를 호출 호출 된 함수 정의의 함수 유형은 정의되지 않습니다.
extern "C" typedef void (*f_t)(Foo*);
int main()
{
Foo foo;
f_t fn = [] (Foo *foo) {
foo->x();
};
fn(&foo); // `fn` is a pointer to a function that uses "C++" language linkage,
// but it is erroneously called through "C" language linkage.
//...
편집 : 실험 조금 후에, 나는 주어진 멤버 함수를 호출 람다를 돌려 다음 템플릿 기능을 함께했다 :
그래서 다음과 같은 기술적으로 정의되지 않은 동작을 호출
:
Foo
만약
template <typename return_t, class base, typename... arg_types>
std::function<return_t (base*, arg_types...)> make_lambda_to_call_member_function(return_t (base::*mem_fn)(arg_types...))
{
return [mem_fn] (base *o, arg_types... args) -> return_t {
(o->*mem_fn)(args...);
};
}
template <typename return_t, class base, typename... arg_types>
std::function<return_t (const base*, arg_types...)> make_lambda_to_call_member_function(return_t (base::*cmem_fn)(arg_types...) const)
{
return [cmem_fn] (const base *o, arg_types... args) -> return_t {
(o->*cmem_fn)(args...);
};
}
는 다음과 같이 정의된다 람다 표현식이 람다 캡처를 사용하기 때문에 반환 된 람다 개체를 암시 적으로 함수 포인터로 변환되지 않습니다, 그러나,
auto fn = make_lambda_to_call_member_function(&Foo::x);
fn(&foo);
auto fn1 = make_lambda_to_call_member_function(&Foo::x1);
fn1(&foo, 314);
auto fn2 = make_lambda_to_call_member_function(&Foo::cx1);
fn2(&foo, 44.832f);
참고 :
struct Foo
{
void x() { cout << "Foo::x()" << endl; }
void x1(int i) { cout << "Foo::x1(" << i << ")" << endl; }
void cx1(float f) const { cout << "Foo::cx1(" << f << ")" << endl; }
};
617,451,515,는 그런 다음 같은 템플릿 make_lambda_to_call_member_function
를 사용합니다.
C++ 0X의 최신 초안, n3225, 상태 :
없는 람다 캡처와 람다 표현 닫는 방법의 종류는 공개되지 않은 가상이 아닌 명시 적 CONST있다 변환 함수는 동일한 매개 변수를 갖는 함수를 가리키는 포인터 및 클로저 유형의 함수 호출 연산자와 같은 리턴 유형을 가리 킵니다. 이 변환 함수가 반환하는 값은 호출 될 때 클로저 형식의 함수 호출 연산자를 호출하는 것과 동일한 효과를 갖는 함수의 주소 여야합니다.
다음은 불법입니다 :
는
void (*fn5)(Foo*) = make_lambda_to_call_member_function(&Foo::x);
당신이 사용하는 어떤 컴파일러? C++ 0x를 사용할 수 있다면 캡쳐리스 (capture-less) 인 람다 (lambda)를 사용하면 함수 포인터로 변환 할 수 있습니다. 또한 왜 동적으로'main'에 어떤 것을 할당할까요? – GManNickG
'new'는 무시합니다. - 질문에는 중요하지 않습니다. 나는 GCC 4.5와 ICC 11.1을 사용한다. 'Lambda 함수는 구현 의존형의 함수 객체이기 때문에'lambda가 여기서 어떻게 도움이되는지 잘 모르겠습니다. 사실, 나는 C++ 0x를 잘 모른다. 코드 예제가 인정된다. – klimkin
이 질문이 ** 아마도 ** http://codereview.stackexchange.com/ –