VS 2010 (Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
)에서 이것을 재현 할 수 있으며 버그라고 생각합니다. 진실은, 여기에 관련된 범위 문제를 내 머리를 감싸는 힘든 시간을 보내고있다,하지만 그게 바로 옆에있는 문제에 아무런 영향을 미치지 않는 것 같다 (기본 템플릿과 전문화가 함께 중첩되어 있고 VS가 재귀 수준에 대해 불평하고있다. , 정의되지 않은 기호가 아님). 어쨌든 매우 흥미로운 예입니다. 또한 VS 2005 (Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
)에서 동일한 동작이 발생합니다. Microsoft가 VS 2010 (버그 번호 : Microsoft Connect Visual Studio page 및 feedback form으로 판단)에서 여전히 버그 보고서를 수락하지 않는 것 같습니다. 문제가 아직 해결되지 않은 경우 VS 2012에 대한 액세스 권한이있는 사람이 원본 코드를 테스트하고 버그 보고서를 제출할 수 있기를 바랍니다. (이전에 Microsoft의 관심을 끌지 못했음)
이 문제를 해결하려면, 앞으로 재귀의 원인 클래스 템플릿 선언
// Forward declaration of problematic inherited class template
template<template<int> class A, int n = 0, typename obj_type = typename A<n>::type>
struct Instantiate;
template<template<int> class A, int n>
struct Instantiate<A,n,void>
{
};
// Now compiles!
template<typename O>
struct test
{
template<int n, bool=true> struct array { typedef void type; };
template<int n> struct array2 { typedef typename array<n>::type type; };
template<bool u> struct array<0,u> { typedef int type; };
template<bool u> struct array<1,u> { typedef float type; };
template<bool u> struct array<2,u> { typedef bool type; };
Instantiate<array2> objects;
};
// Instantiate each type of a type array (which is a template<int>)
// void is taken as the end of the array
template<template<int> class A, int n, typename obj_type>
struct Instantiate : public Instantiate<A,n+1>
{
obj_type object;
Instantiate() : object() {}
};
int main()
{
test<int> obj;
return 0;
}
편집을
의 Synxis의 rise4fun 링크를 주셔서 감사합니다, 그것은 나중에 편리하게 할 수 있는지의 . 놀라운 점은 원래 코드가 VS2012 CTP
에서 정상적으로 작동하지만 여전히 VS2012 RTM
에서 오류가 발생했다는 것입니다. http://rise4fun.com/Vcpp/aRh을 참조하십시오. 왜 이 RTM
이 아닌 기본 옵션이되는 이유는 무엇입니까? 이 예제는 확실히 이상한 것입니다.
test
에 의해 사용되는 라이브러리 헤더에 Instantiate
이외의 것이 있습니까? 그렇지 않은 경우 사용자는 명시 적으로 Instantiate
템플릿을 선언하여 test
을 정의한 다음 헤더를 포함시킬 수 있습니다.그렇지 않으면 필요한 다른 것들과 함께 forward 선언이있는 헤더 파일을 만들 수 있습니다. 대부분이 문제의 영향을받는 사용자를 위해 특수한 해결 방법 헤더를 만들려고합니다. 이것은 확실히 상황이 매우 혼란과 오류 (주로 인해 기본 템플릿 인수에) 경향이 있습니다,하지만 작동합니다
myLib_workaround_forward_declaration.hpp :
#ifndef MYLIB_WORKAROUND_FORWARD_DECLARATION // or #pragma once if supported
#define MYLIB_WORKAROUND_FORWARD_DECLARATION
// amount of error checking is up to you
// eg, are workaround header files mixed with the regular ones
// or included in the wrong order
template<template<int> class A, int n = 0, typename obj_type = typename A<n>::type>
struct Instantiate;
#endif
myLib_workaround_implementation.hpp :
#ifndef MYLIB_WORKAROUND_IMPLEMENTATION // or #pragma once if supported
#define MYLIB_WORKAROUND_IMPLEMENTATION
// amount of error checking is up to you
// eg, are workaround header files mixed with the regular ones
// or included in the wrong order
template<template<int> class A, int n, typename obj_type>
struct Instantiate : public Instantiate<A,n+1>
{
obj_type object;
Instantiate() : object() {}
};
template<template<int> class A, int n>
struct Instantiate<A,n,void>
{
};
#endif
userFile.cpp :
// Forward declaration of problematic inherited class template
#include "myLib_workaround_forward_declaration.hpp"
// Now compiles!
template<typename O>
struct test
{
template<int n, bool=true> struct array { typedef void type; };
template<int n> struct array2 { typedef typename array<n>::type type; };
template<bool u> struct array<0,u> { typedef int type; };
template<bool u> struct array<1,u> { typedef float type; };
template<bool u> struct array<2,u> { typedef bool type; };
Instantiate<array2> objects;
};
#include "myLib_workaround_implementation.hpp"
int main()
{
test<int> obj;
return 0;
}
유용 할 수 있습니다. http://stackoverflow.com/questions/4357854/c-template-compilation-error-recursive-type-or-function-dependency –
@Shafik 저는 이미 그것을 보았습니다. 그 오류. 어쨌든 고맙습니다. – Synxis
배열 <2,u> 전문화 아래에서 array2 템플릿을 이동하려 했습니까? 차이가 있습니까? – Tomek