Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 依赖于模板参数的内部类_C++_Templates_Metaprogramming_Partial Specialization_Pimpl Idiom - Fatal编程技术网

C++ 依赖于模板参数的内部类

C++ 依赖于模板参数的内部类,c++,templates,metaprogramming,partial-specialization,pimpl-idiom,C++,Templates,Metaprogramming,Partial Specialization,Pimpl Idiom,考虑下一个例子: #include <iostream> #include <typeinfo> template< int N, typename T > struct B { struct C; }; template< typename T > struct B< 0, T >::C { typedef T type; }; template< int N, typename T > struct

考虑下一个例子:

#include <iostream>
#include <typeinfo>

template< int N, typename T >
struct B
{
    struct C;
};

template< typename T >
struct B< 0, T >::C
{
    typedef T type;
};

template< int N, typename T >
struct B< N, T >::C
{
    typedef T type[N];
};

int main()
{
    std::cout<<"n=0   type = " << typeid( B< 0, float >::C::type ).name() << std::endl;
    std::cout<<"n=5   type = " << typeid( B< 5, float >::C::type ).name() << std::endl;
}
编译错误是:

dfg.cpp:13: error: qualified name does not name a class before ‘{’ token
dfg.cpp: In instantiation of ‘B<0, float>::C’:
dfg.cpp:25:   instantiated from here
dfg.cpp:20: error: ISO C++ forbids zero-size array
dfg.cpp:13:错误:限定名未在“{”标记之前命名类
dfg.cpp:在“B::C”的实例化中:
dfg.cpp:25:从此处实例化
20:错误:ISO C++禁止零大小数组
我真正想要归档的是根据枚举值使用不同的Imp实现(在本例中,我使用int而不是枚举,但这并不重要)

有人能解释为什么这是不允许的吗? 为什么我会出现第一个错误? (此:限定名不在“{”标记之前命名类)



关于依赖于模板参数的pimpl实现,我创建了一个新问题(使用更好的示例)您不能用这种方式在
B
外部定义
C
C
对于您正在创建的
B
专门化不存在。如果您想专门化B::C,您需要专门化B。您是否尝试执行以下操作

template< int N, typename T >
struct B
{
    struct C {
        typedef T type[N];
    };
};

template< typename T >
struct B< 0, T >
{
    struct C {
        typedef T type;
    };
};
模板
结构B
{
结构C{
类型定义T类型[N];
};
};
模板
结构B<0,T>
{
结构C{
T型;
};
};
或者,您可以执行以下操作:

template< int N, typename T >
struct B
{
    struct C;
};

template< typename T >
struct B< 0, T > {
    struct C;
};

template< typename T >
struct B< 0, T >::C
{
    typedef T type;
};

template< int N, typename T >
struct B< N, T >::C
{
    typedef T type[N];
};
模板
结构B
{
结构C;
};
模板
结构B<0,T>{
结构C;
};
模板
结构B<0,T>::C
{
T型;
};
模板
结构B::C
{
类型定义T类型[N];
};
这部分专用于0的B,并向前声明C,因此可以定义
B::C

这是无效的:

template< typename T >
struct B< 0, T >::C
{
    typedef T type;
};
模板
结构B<0,T>::C
{
T型;
};
您可以专门化类模板的成员,但仅限于这些类模板的隐式实例化。这在简单的英语中意味着:仅当您为封闭类模板(您需要专门化其成员)的所有模板参数提供值时

模板<>
结构B<0,int>::C
{
T型;
};
您编写的是a
B::C
的定义,它是
B
的类模板部分专门化的成员。这种部分专门化不存在,因此编译器出错


你有几个选择来解决这个问题。一个是

template< int N, typename T >
struct B
{
    template<typename N1, typename T1>
    struct CMember { typedef T1 type[N1]; };

    template<typename T1>
    struct CMember<0, T1> { typedef T1 type; };

    struct C { 
      typedef typename CMember<N, T>::type type;
    };
};
模板
结构B
{
模板
结构CMember{typedef T1 type[N1];};
模板
结构CMember{typedef T1 type;};
结构C{
typedef typename CMember::type type;
};
};
请注意,显式专门化(非部分)不能直接放入类模板中(因此,
template struct CMember{…}
B
的主体中写入时格式不正确)。您需要在
B
之外定义“选择器”模板(可能在
详细信息
命名空间中)


其他替代方法包括从
CMember
派生并继承其typedef。

不太可能。我正在使用pimpl习惯用法,并试图根据模板参数对其进行不同的实现。您可以在struct B中向前声明struct C,并在外部定义它,但两者都必须在INstationvjo:你的帖子里没有pImpl……我发布的内容给了你
n=0 type=float
n=5 type=float[5]
-你想实现什么?结构C模拟pimpl习惯用法,因为它是在结构B中正向声明的。因此,我必须声明结构B的模板专门化才能工作?为什么它不能使用B的声明它就在那里?@VJo:没有什么阻止你,例如,创建一个B专门化at根本没有
结构C
。因此编译器无法知道
B
的专门化有
C
成员,除非你告诉它,向它显示专门化。好的,我将创建一个新问题
template< >
struct B< 0, int >::C
{
    typedef T type;
};
template< int N, typename T >
struct B
{
    template<typename N1, typename T1>
    struct CMember { typedef T1 type[N1]; };

    template<typename T1>
    struct CMember<0, T1> { typedef T1 type; };

    struct C { 
      typedef typename CMember<N, T>::type type;
    };
};