C++ 에 template 사용시 에러 질문

B00m의 이미지

//1
template <typename T>
struct A
{
	struct a {};
};

template <typename T>
struct B : A<T>
{
	void foo(A<T>::a v) {
	}
};


//2
template <typename T>
struct C {
	template <int v> struct a {};

	template <> struct a<0> {};
};

위의 코드가 VC8 에서는 정상적으로 돌아갔던 소스인데 gcc 에서 컴파일하니 에러가 나네요.

a.cpp:11: error: `struct A<T>::a' is not a type
a.cpp:11: error: ISO C++ forbids declaration of `v' with no type
a.cpp:21: error: invalid explicit specialization before '>' token
a.cpp:21: error: explicit specialization in non-namespace scope `struct C<T>'
a.cpp:21: error: enclosing class templates are not explicitly specialized
a.cpp:21: error: template parameters not used in partial specialization:
a.cpp:21: error:         `T'

제 생각에는 gcc 정확한거 같긴한데, 정확히 C++ 표준에 이 부분에 대해 어떻게 정의되어 있는지 모르겠네요.

조언 부탁드리겠습니다.

쌀밥의 이미지

1번의 경우는
//1
template <typename T>
struct A
{
struct a {};
};

template <typename T>
struct B : A<T>
{
void foo(typename A<T>::a v) {
}
};
이렇게 하시면 될듯합니다.
A<T>의 코드가 생성되기 전까지는 A<T>::a 를 인식하지 못하기 ㅤㄸㅒㅤ문에 나오는 에러 메시지인듯합니다.

일하는 사람들의 희망 민주노동당 : http://www.kdlp.org
반공 교육의 성과로, 민주주의의 반대가 공산주의(또는 사회주의)라고 생각하는 사람이 많다.

doldori의 이미지

첫번째 문제는 쌀밥님의 답변대로 하시면 되겠고...

두번째 문제는 클래스 템플릿의 멤버 템플릿을 전문화하겠다는 의도인 듯한데,
이런 식으로는 안됩니다. 멤버 템플릿의 전문화는 그 멤버를 포함하는 클래스의
전문화가 선행되어야 하기 때문입니다.

template <typename T> 
struct C { 
   template <int v> struct a {};  // (1)
}; 

template <> 
  template <>
  struct C<int>::a<0> {};  // (2)

C<int>::a<1> ci1;   // primary template (1)
C<char>::a<0> cc0;  // primary template (1)
C<int>::a<0> ci0;   // specialized (2)
B00m의 이미지

쌀밥 wrote:
1번의 경우는
//1
template <typename T>
struct A
{
struct a {};
};

template <typename T>
struct B : A<T>
{
void foo(typename A<T>::a v) {
}
};
이렇게 하시면 될듯합니다.
A<T>의 코드가 생성되기 전까지는 A<T>::a 를 인식하지 못하기 ㅤㄸㅒㅤ문에 나오는 에러 메시지인듯합니다.

앗 typename 넣어보는걸 깜박했네요. 감사합니다.

doldori wrote:
첫번째 문제는 쌀밥님의 답변대로 하시면 되겠고...

두번째 문제는 클래스 템플릿의 멤버 템플릿을 전문화하겠다는 의도인 듯한데,
이런 식으로는 안됩니다. 멤버 템플릿의 전문화는 그 멤버를 포함하는 클래스의
전문화가 선행되어야 하기 때문입니다.

template <typename T> 
struct C { 
   template <int v> struct a {};  // (1)
}; 

template <> 
  template <>
  struct C<int>::a<0> {};  // (2)

C<int>::a<1> ci1;   // primary template (1)
C<char>::a<0> cc0;  // primary template (1)
C<int>::a<0> ci0;   // specialized (2)

답변 감사합니다..

근데 2번째의 경우

template <typename T>
struct C {
   template <int a, int b> struct c {};

   template <int a> struct c<a, 0> {};
};

위와 같은 코드는 가능하던데..

부분 전문화만 가능한 건가요?

관련 내용이 설명된 문서도 못찾겠고 정확한 정의가 어떻게 되는건지 모르겠네요.

doldori의 이미지

네, 부분 전문화이기 때문에 가능합니다. 다음은 표준에서 인용한 것입니다.

Quote:
14.5.2/1
A template can be declared within a class or class templates; such a
template is called a member template. A member template can be
defined within or outside
its class definition or class template definition. [...]

14.5.4.3/2
If a member template of a class template is partially specialized,
the member template partial specializations are member templates of
the enclosing class template; [...]

14.7.3/18
In an explicit specialization declaration for a member of a class
template or member template that appears in namespace scope,
the member template and some of its enclosing class template may
remain unspecialized, except that the declaration shall not explicitly
specialize a class member template if its enclosing class templates are
not explicitly specialized as well.
[...] [Example:


template<class T1> class A {
    template<class T2> class B {
        template<class T3> void mf1(T3);
        void mf2();
    };
};
    
template<> template<class X>
class A<int>::B { };
    
template<> template<> template<class T>
void A<int>::B<double>::mf1(T t) { }
    
template<class Y> template<>
void A<Y>::B<double>::mf2() { }  // ill-formed; B<double> is specialized but
                                 // its enclosing class template A is not.

처음 코드의 경우 전문화된 struct a<0>은 멤버 템플릿이 아니므로 14.5.2/1에 의하여
struct C 내부에서 정의할 수 없고 14.7.3/18에 의하여 전문화되지 않은 struct C의
전문화된 struct a<0>을 정의한 것이므로 에러입니다.
두번째 코드의 경우 부분 전문화된 struct c<a, 0>은 역시 멤버 템플릿이고 이때
struct C 내부에서 정의할 수 있으므로 적법합니다. 물론 struct C의 외부에서
부분 전문화를 정의할 수도 있습니다.
template <typename T> 
struct C { 
   template <int a, int b> struct c {}; 
}; 

template <typename T>
  template <int a>
  struct C<T>::c<a, 0> {};
oosap의 이미지

Thanks for being one of those who care for people and mankind.
I'd like to be one of those as well.

댓글 달기

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]. PHP 소스 코드는 다음과 같이 사용할 수 있습니다: <?php ... ?> 또는 <% ... %>.
  • 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]. PHP 소스 코드는 다음과 같이 사용할 수 있습니다: <?php ... ?> 또는 <% ... %>.
  • 사용할 수 있는 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]. PHP 소스 코드는 다음과 같이 사용할 수 있습니다: <?php ... ?> 또는 <% ... %>.
  • 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]. PHP 소스 코드는 다음과 같이 사용할 수 있습니다: <?php ... ?> 또는 <% ... %>.
  • 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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.