[질문]함수 템플릿의 함수 포인터를 쓰려면?

paraline의 이미지

template <class T>
void test(T a, T b);

template <class T>
void (*func)(T a, T b);

위와 같이 함수 템플릿인 test 함수의 함수 포인터를 사용하기 위해, (*func)라는 함수 포인터를 선언했습니다.
그런데, 컴파일을 하면,

template declaration of `void (* func)(T a, T b)'

이런 에러가 발생하는군요.

함수 템플릿의 함수 포인터 사용은 불가능한건가요?
아니면, 제가 잘못 쓴건가요?

한수 지도 바랍니다.

답변 주실 모든 분들께 미리 감사의 말씀 전합니다.

doldori의 이미지

템플릿은 클래스나 함수를 정의할 때만 쓰일 수 있으며 개체 자체를 템플릿으로
정의할 수는 없습니다.

template<typename T> T a;

이런 것은 당연히 안되지요.
템플릿 함수에 대한 포인터라고 해서 별다른 것은 없고 type parameter만
명시하면 됩니다.

template <class T> 
void test(T a, T b)
{
	void (*func)(T, T) = test<T>;
}

int main()
{
	void (*func)(int, int) = test<int>;
}
paraline의 이미지

template <class T> 
void test(T a, T b)
{
	void (*func)(T, T) = test<T>;
}

int main()
{
	void (*func)(int, int) = test<int>;
}

제가 원하는것은 main()안에서, void (*func)(T, T) = test<T>;라고 쓰는것입니다. 그래야, test의 파라미터에 상관없이, (*func)로 받을수 있을것 같아서요. 그런데, 문제는 그냥 void (*func)(T, T) 이렇게 하면, T 타입이 뭔지를 모르기 때문에 에러가 발생하고, 그렇다고, 질문과 같이 template <class T>를 붙여주면 또 다른 에러가...
만약에 다음과 같이 각각의 파라미터 타입에 맞는 함수 포인터를 선언한다면,

void (*func)(int, int) = test<int>;
void (*func)(long, long) = test<long>;
void (*func)(double, double) = test<double>;

함수 포인터를 사용하는 의미가 없을것 같은데요.

명확하게 질문을 못하니까, 답답하군요.
아시겠지만, 제 질문의 요지는 함수 템플릿 처럼 파라미터 타입에 구애받지 않는 함수 포인터를 선언하고 싶은건데요. 조언 부탁드립니다.

좌절금지!!!
피할수 없다면 즐겨라.

doldori의 이미지

저도 어떤 것을 원하시는지 정확히 파악을 할 수 없긴 한데, 아마 임의의 형의
함수 포인터를 인자로 취하는 함수를 원하시는 게 아닐까 합니다. 그렇다면
그 함수 자체를 템플릿으로 만들면 됩니다.

void f(int);
int g(double);
void h();

template<typename Arg, typename FunctionPointer>
void test(Arg a, FunctionPointer fp)
{
	(*fp)(a);
}

int main()
{
    test(1, f);
    test(2, g);
    test(3, h);
}

f()나 g()가 취하는 인자의 갯수까지 변할 수는 없습니다. 즉 test(3, h) 같은 것은
에러라는 것이죠. 이와 관련하여 표준 라이브러리에서 제공하는 functor 클래스를
참고하시면 도움이 될 듯 합니다.
mtorange의 이미지

paraline wrote:
template <class T> 
void test(T a, T b)
{
	void (*func)(T, T) = test<T>;
}

int main()
{
	void (*func)(int, int) = test<int>;
}

제가 원하는것은 main()안에서, void (*func)(T, T) = test<T>;라고 쓰는것입니다. 그래야, test의 파라미터에 상관없이, (*func)로 받을수 있을것 같아서요. 그런데, 문제는 그냥 void (*func)(T, T) 이렇게 하면, T 타입이 뭔지를 모르기 때문에 에러가 발생하고, 그렇다고, 질문과 같이 template <class T>를 붙여주면 또 다른 에러가...
만약에 다음과 같이 각각의 파라미터 타입에 맞는 함수 포인터를 선언한다면,

void (*func)(int, int) = test<int>;
void (*func)(long, long) = test<long>;
void (*func)(double, double) = test<double>;

함수 포인터를 사용하는 의미가 없을것 같은데요.

명확하게 질문을 못하니까, 답답하군요.
아시겠지만, 제 질문의 요지는 함수 템플릿 처럼 파라미터 타입에 구애받지 않는 함수 포인터를 선언하고 싶은건데요. 조언 부탁드립니다.

아래와 같이 해결 가능합니다. 이것을 원하신게 맞나요?


template <typename T>
class TYPE
{
public:
    typedef void (*fptr)(T, T) ;
};

template <typename T>
void foo(T a, T b)
{
... 
}

int main()
{
    TYPE<int>::fptr func = foo;
    (*func)(1, 2);
    return 0;
}

paraline의 이미지

mtorange wrote:
아래와 같이 해결 가능합니다. 이것을 원하신게 맞나요?


template <typename T>
class TYPE
{
public:
    typedef void (*fptr)(T, T) ;
};

template <typename T>
void foo(T a, T b)
{
... 
}

int main()
{
    TYPE<int>::fptr func = foo;
    (*func)(1, 2);
    return 0;
}

제가 질문했던 요지와 가장 근접한 답변입니다.
물론, 제가 원한건, 함수 포인터가 클래스안에 선언되지 않고, 그냥 전역으로 선언하길 원했던 것이지만, 님께서 제시하신 방법이 아니면, T 타입을 인식할수 없으니 어쩔수가 없겠네요.

질문자체가 충분치 않아서 전달이 제대로 안된것 같습니다.
제 질문의 본래 의도는 다음과 같습니다.

template <typename T>
void Plus(T a, T b)
{
   return (a + b);
}
template <typename T>
void Minus(T a, T b)
{
    return (a - b);
}

int main()
{
    int (*func)(T a, T b);
    int a = 1, b = 2, c = 3;
    if(a == 1)
    {
        func = Plus;
    }
    else
    {
        func = Minus;
    }

    func(b, c);

    return 0;
}

파라미터의 타입이 무엇이든 상관없이 쓰려고, 함수 템플릿을 사용했고, 그 함수 템플릿의 포인터를 함수 포인터로 받아서 쓰려는 것이었는데, 함수 포인터를 타입별로 만들어서 쓰자니, 함수 템플릿을 사용하는 의미가 없을것 같고 해서, 질문을 하게 되었습니다. 역시나 T 타입을 쓰기 위해서는 클래스에서 선언하는 수밖에는 없겠네요. :oops:

제가 맞게 생각하고 있는지 모르겠습니다. ㅠ.ㅠ

제가 너무 바보같은 질문을 드렸습니다. 덕분에 많이 배웠습니다만...
답변주신 모든 분들께 감사의 말씀을 전합니다. ^^

좌절금지!!!
피할수 없다면 즐겨라.

doldori의 이미지

이런 것은 표준 라이브러리를 사용해도 충분히 가능합니다. 함수 포인터 func를
정의할 필요도 없지요.

#include <functional>

template<typename T>
T f(T, T);

int main()
{
	int a = 1, b = 2, c = 3;
	if (a == 1)
		std::plus<int>()(b, c);
	else if (a == 2)
		std::minus<int>()(b, c);
	else
		std::ptr_fun(f<int>)(b, c);
}
paraline의 이미지

doldori wrote:
이런 것은 표준 라이브러리를 사용해도 충분히 가능합니다. 함수 포인터 func를
정의할 필요도 없지요.
#include <functional>

template<typename T>
T f(T, T);

int main()
{
	int a = 1, b = 2, c = 3;
	if (a == 1)
		std::plus<int>()(b, c);
	else if (a == 2)
		std::minus<int>()(b, c);
	else
		std::ptr_fun(f<int>)(b, c);
}

답변 감사합니다.
윗글은 그냥 예일뿐입니다.
진짜 plus, minus를 하려는게 아니고요. ^^

좌절금지!!!
피할수 없다면 즐겨라.

myueho의 이미지

그렇다면 functional 해더파일을 직접 열어보면 되겠네요. :)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.