2010-05-28 3 views
4

여기에 까다로운 상황이며, 내가 그것을이름없는 네임 스페이스에서 숨겨진 템플릿에 액세스하는 방법은 무엇입니까?

namespace { 
    template <class T> 
    struct Template { /* ... */ }; 
} 

typedef Template<int> Template; 

안타깝게도 Template 타입 정의의 이름이 네임 스페이스의 Template 템플릿을 방해 해결하기 위해 거기에 어떤 방법으로 궁금하다. 전역 범위에서 Template<float>을 수행하려고하면 컴파일러에서 템플릿 이름과 typedef 이름 사이에 모호한 오류가 발생합니다.

템플릿 이름이나 typedef-name을 제어 할 수 없습니다.

  • 글로벌 네임 스페이스의 typedefed 유형 Template (즉 Template<int>)의 객체를 생성 : 지금은이 행 수 있는지 알고 싶어요.
  • 전역 이름 공간에 Template<float> 유형의 개체를 만듭니다.

아니요,은 이름이없는 네임 스페이스에 아무 것도 추가 할 수 없습니다. 모든 것은 전역 네임 스페이스에서 수행되어야합니다.

이러한 모호성을 해결하기 위해 어떤 트릭이 있는지 궁금 해서요. 일상적인 프로그래밍 중에 나는 실제적인 문제가 아닙니다.

+0

실용적인 것보다 재미있는 호기심 질문이 더 많기 때문에 커뮤니티 위키로 만들고 있습니다. :) –

+0

모든 clang/gcc/comeau에서 컴파일되는 두 번째 문제에 대한 해결책은 적어도 하나 있지만 * 찾기가 더 어려워졌습니다. –

+0

완전히 생각할 시간이 없습니다. ,하지만 할당 자들이 템플릿 매개 변수를 변경하는 데 사용하는 트릭을 가지고 있지 않습니까? 여기에서 비슷한 것을 할 수 있고, Rebind <:: Template, float> :: type' 라인을 따라 뭔가를 끝낼 수 있습니까? 그런 식으로,'Template'은'Rebind' 안에서'T'라고 이름이 바뀔 것이고, 모호성은 없습니다. –

답변

0

나는 그것이 다소 당신의 요점을 망쳐 놓는다는 것을 안다. 그러나 나는 주된 트릭이 전염병처럼 이것을 피하는 것이라고 생각한다.

0

그것은 네임 스페이스에 대한 명시 됨으로써 글로벌 typedefed 템플릿에 액세스하는 것이 가능하다, 즉

::Template a 

는 익명의 공간에서 Template<int>입니다. Template<float>을 얻을 수 있는지 확실하지 않습니다. 이렇게하는 이유, 나도 몰라 아마 누군가에게 엄하게 말하는 것 :

#include <iostream> 
namespace { 
    template <class T> 
     struct Template {T value;};} 
typedef Template<int> Template; 

int main(){  
    ::Template a; 
    Template<float> b; 
    a.value = 6; 
    b.value = 3.14; 
    std::cout<<a.value<<" "<<b.value<<"\n"; 
} 
+0

그래, clang은 그 사실을 받아 들일만큼 정확하지 않습니다. Comeau와 GCC도 그것을 금하고 있습니다 :) Good find, 당신은 그것을보고 할 것인가, 아니면 그것을해야합니까? –

+0

나는 이것을이 테스트 케이스로 축소했다. http://codepad.org/pnrSlhPq –

+0

@Johannes 덕분에 http://llvm.org/bugs/show_bug.cgi?id=7251로보고했다. –

-1

면책 조항 :

은 놀랍게도 Clang의 C++ 컴파일러는 아마 다음하지 표준 동작 괜찮습니다 누가 그랬어. C를 사용하여

namespace 
{ 
    template <typename T> class Template { }; 
} 

typedef Template<int> IntTemplate; 
typedef Template<float> FloatTemplate; 
typedef IntTemplate Template; 

int main() { 
    ::Template t; 
    FloatTemplate ft; 
} 
+0

흠,'typedef 템플릿 템플릿;은 어떻게 든 당신의 대답에 사라졌습니다 :) 그것은 하나의 블록을 의미했습니다. 사실 이후에 모든 것이 추가되어야합니다. 그래서 어려운 일입니다 :) –

+0

오, 나는 네임 스페이스 내부의 내용 만 바꿀 수 없다고 생각했습니다. 기본적으로, 당신이하려는 것은 무엇이든 잘못되었습니다. "내부"의 것을 숨기고 오래된 정의와 새로운 정의를 모두 사용하려고 시도하는 것은 의미가 없습니다. –

+1

완전히 의미가 없습니다. 그것은 언어 변호사의 질문입니다. 그것은 감각적 인 소프트웨어 조각에 연결되어 있지 않습니다. –

1

+ +0 : 분명히 그것은 Cormeau으로 컴파일하지만 난 단지 온라인 테스트에 액세스 할 수있는, 그래서 '

void PrintType() [with T = <unnamed>::Template<int>] 
void PrintType() [with T = <unnamed>::Template<float>] 

를 산출 gcc45와

namespace { 
    template<class T> struct Template { }; 
} 
typedef Template<int> Template; 

#include<iostream> 

template<typename T> 
void PrintType() { 
    std::cout << __PRETTY_FUNCTION__ << std::endl; 
} 

template<typename FullType, typename NewParameter> 
class Rebind { 
    template<template<class> class Template, typename OldParameter> 
    static Template<NewParameter> function(Template<OldParameter>); 

public: 
    typedef decltype(function(FullType())) NewType; 
}; 

int main() 
{ 
    PrintType< ::Template>(); 
    PrintType<Rebind< ::Template, float>::NewType>(); 
    return 0; 
} 

그냥 예상대로 작동한다고 가정합니다.

구조체에 실제 형식을 직접 전달하고 템플릿 형식으로 변환하는 방법을 찾지 못했지만 컴파일러는 함수 매개 변수를 추측해야 할 때 두 가지를 제거하는 데 아무런 문제가 없었습니다. 어쩌면 이것은 C++ 03에서 decltype 대신에 boost::result_of을 사용하지만, 전에는 사용 해본 적이 없기 때문에 내가 아는 것에 집중할 것이라고 생각했습니다.

간격은 main입니다.변이가 <:이기 때문에 Rebind<::Template, float>::NewType은 파서에 의해 도깨비가됩니다. 나는 그것이 Rebind[:Template, float>::NewType으로 바뀌 었다고 생각한다. 따라서 ::Template 전의 공간이 중요합니다.

제쳐두고 중첩 된 템플릿 매개 변수는 template<template<typename> typename T>이 아닌 [template<template<typename> class T>]을 사용할 수 없다는 것을 알았습니다. 나는 구문에 대한 구문을 기억하려고 할 때마다 그 점을 다시 읽었다 고 생각합니다.

+0

아 답답해하면서 C++ 03에서이 질문을 해결할 두 번째 방법을 생각하게되었습니다. 당신은 실제로 그것을 해결하기 위해 두 번째 방법을 사용하여 닫고 있습니다 :) –

관련 문제