C++ 模板化重复类型错误

C++ 模板化重复类型错误,c++,visual-studio-2010,templates,C++,Visual Studio 2010,Templates,我在VS2010中遇到了一个奇怪的问题。以下代码无法编译(正在运行时): 这不是bug,而是编译器配置。编译时堆栈和运行时堆栈一样受到限制。IIRC in VS编译时堆栈的最大深度为512。可能值得在文档中查找,也许它是可配置的,但不确定。我可以在VS2010中重现这一点(使用Microsoft(R)32位C/C++优化编译器版本16.00.40219.01 for 80x86),我相信这是一个bug。说实话,我很难理解这里涉及的范围问题,但这似乎与手头的问题无关(因为基本模板和专门化嵌套在一起

我在VS2010中遇到了一个奇怪的问题。以下代码无法编译(正在运行时):


这不是bug,而是编译器配置。编译时堆栈和运行时堆栈一样受到限制。IIRC in VS编译时堆栈的最大深度为512。可能值得在文档中查找,也许它是可配置的,但不确定。

我可以在VS2010中重现这一点(使用Microsoft(R)32位C/C++优化编译器版本16.00.40219.01 for 80x86),我相信这是一个bug。说实话,我很难理解这里涉及的范围问题,但这似乎与手头的问题无关(因为基本模板和专门化嵌套在一起,VS抱怨的是递归级别,而不是未定义的符号)。无论如何,这是一个非常有趣的例子。我在VS2005中也看到了同样的行为(使用Microsoft(R)32位C/C++优化编译器版本14.00.50727.762 for 80x86)。微软似乎还没有接受VS2010的bug报告(根据和判断)。如果问题还没有解决(我认为这很有可能,我看不出有任何迹象表明之前微软已经注意到了这一点),那么有希望能够访问VS 2012的人能够测试您的原始代码并提交错误报告

要解决此问题,请向前声明导致递归的类模板:

// 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;
}
myLib\u解决方案\u实施。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
#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
// 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;
}
#ifndef MYLIB#u解决方案#实现//或#pragma一次(如果支持的话)
#定义MYLIB_解决方案_实现
//错误检查的数量由您决定
//例如,变通方法头文件是否与常规头文件混合
//或者包含在错误的顺序中
模板
结构实例化:公共实例化
{
obj_型对象;
实例化():对象(){}
};
模板
结构实例化
{
};
#恩迪夫
userFile.cpp

#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
#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
// 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;
}
//有问题的继承类模板的转发声明
#包括“myLib\u解决方案\u转发\u声明.hpp”
//现在编译!
模板
结构测试
{
模板结构数组{typedef void type;};
模板结构array2{typedef typename数组::type type;};
模板结构数组{typedef int type;};
模板结构数组{typedef float type;};
模板结构数组{typedef bool type;};
实例化对象;
};
#包括“myLib\u工作区\u实现.hpp”
int main()
{
测试对象;
返回0;
}

在处理rise4fun和jerry的解决方案时,我发现将
的整个定义实例化
放在
测试中(有关VS2012CTP与VS2012RTM的更多信息,请参见jerry的回答):

模板
结构测试
{
模板
结构实例化:公共实例化
{
obj_型对象;
实例化():对象(){}
};
模板
结构实例化
{
};
模板结构数组{typedef void type;};
模板结构array2{typedef typename数组::type type;};
模板结构数组{typedef int type;};
模板结构数组{typedef float type;};
模板结构数组{typedef bool type;};
实例化对象;
};
int main()
{
测试对象;
}

这非常适合我的用例,因为它可以包含在用户已经使用过的宏中。

这可能很有用@Shafik我已经看过了,但不是那个错误。无论如何,谢谢。您是否尝试将array2模板移到数组专用化下面?它有区别吗?@Tomek是的,我试过了,但它也不编译。gcc也是一样。此外,类型数组只有3个元素。因此它应该在
n==3
处停止递归,这对应于
void
专门化。GCC就是这样做的。今晚我将在VS2010上测试这段代码,目前它在VS2012(问题中的版本也是)上工作得非常完美。此解决方案的问题是在
测试之后定义
实例化
。在我的例子中,
test
是由用户提供的,而
实例化是由我的库提供的+1无论如何。如果您找到其他解决方法/解决方案,请随时发布:)!所以CTP!=RTM。好极了。。。我想到了您在编辑中采用的变通方法,但并不实用(您必须确保用户不会忘记包含实现标题)。在处理r4f rtm时,我发现了另一个不包含2个头的解决方案。谢谢你的回答!啊,忘了说:。享受吧@Synxis现在是一个报告的bug:很高兴您找到了一个适用于您的库的解决方案。出于好奇,它会公开吗?是的。这将是(主页被窃听,你可能会在论坛和源代码中找到更多信息)的一部分。
template<typename O>
struct test
{
    template<template<int> class A, int n = 0, typename obj_type = typename A<n>::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>
    {
    };

    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;
};

int main()
{
   test<int> obj;
}