std :: function 및 std :: bind를 가지고 놀려고했는데 문제가있었습니다. 멤버 함수의 선험적 인 인수를 모른 채 멤버 함수에 std :: function을 바인딩 할 수있는 일반 구조를 만들고 싶습니다. 내가std :: function에서 액세스 위반이 람다에게 할당되었습니다.
template<typename Class, typename Return, typename ...Args>
struct Caller
{
private:
std::function<Return(Args ...)> callerFunction;
Caller(const Caller&) = delete;
Caller(Caller&&) = delete;
Caller& operator=(const Caller&) = delete;
public:
~Caller() = default;
Caller() = default;
Caller(Class& instance, Return(Class::*function)(Args...))
{
callerFunction = [&](Args... args) { return (instance.*function)(args...); };
}
Return operator() (Args ... args)
{
return callerFunction(args...);
}
};
가 참고로 나는 함수의 인수가 값에 의해 전달되는 것을 알고이 일을 썼다 (I는 가변 인자 템플릿 보편적 참조를 사용하여 몇 가지 문제가 발생, 그 이후에 작동합니다).
여기서 문제는 operator()로 함수를 실행하면 액세스 위반 오류가 발생한다는 것입니다. 내가 문제를 좁히려 고 variadic 인수 (멤버 함수가 int를 인수로 가질 수 있도록 허용)없이 구조체를 만들려고했는데 std :: function에 람다를 할당하는 것이 나에게 같은 오류를 주었다. 그러나 if std :: bind를 placeholder와 함께 사용하면 모든 것이 잘되었습니다.
테스트 지상 내가 제대로 멤버 함수를 호출하기 위해 클래스의 인스턴스를 저장해야 할, 람다를 사용하여이
class A
{
public:
bool foo(int a)
{
std::cout << a << std::endl;
return true;
}
};
int main()
{
A a;
a.foo(9);
Caller<A, bool, int> caller(a, &A::foo);
caller(10);
std::cin.ignore();
}
입니까?
나는 UB를 가졌을 것이라고 확신한다. 'Caller'의 생성자에서는 멤버 함수 포인터를 값으로 전달합니다 (그래서 생성자 내부에만 존재하는 포인터 복사본이 생성됩니다). 그런 다음 참조로 람다에서 그 함수를 캡처합니다. 그래서'caller (10) '이라고 부를 때쯤에 포인터가 범위를 벗어납니다. 'instance'는 생성자에게 참조로 전달하기 때문에이 예제에서는 괜찮습니다. 그리고'caller (10)'을 호출 할 때'a'는 여전히 범위 내에 있습니다. (당신이 미래에 그것을 바꿀 것이라고 가정해야한다.) – 0x5453
lambda 나'std :: bind'에서 잘 동작 할'std :: mem_fn' 파일이 이미 존재한다는 점도 주목할 가치가있다. – 0x5453
알았습니다. 내가 이해할 수없는 것은이 문제를 어떻게 해결할 수 있는가하는 것이다. 인스턴스 정보 : 프로그램을 시작할 때 일부 클래스가 인스턴스화되고 해당 변수는 프로그램이 끝날 때까지 사용할 수 있습니다. – Astinog