使用前向声明在转换运算符中使用不完整类型无效

时间:2014-05-08 14:03:33

标签: c++ templates c++11

我在这样的头文件中定义了一个类(虽然这是一个精简版本):

my_class.hpp

// header guard

template<typename T, std::size_t First, std::size_t Second, class Enable = void>
class other_class;

template<typename T, std::size_t Size, class Enable = void>
class my_class;                        // I have my reasons

template<typename T, std::size_t Size>
class my_class<T, Size, typename std::enable_if<condition1>::type>{
    public:
        template<
                std::size_t S = Size,
                typename = typename std::enable_if<other_condition1>::type
        >
        operator other_class<T, 1, Size>();
};

template<typename T, std::size_t Size>
class my_class<T, Size, typename std::enable_if<condition2>::type>{
    public:
        template<
                std::size_t S = Size,
                typename = typename std::enable_if<other_condition2>::type
        >
        operator other_class<T, 1, Size>();
};

然后是头文件中的另一个类:

other_class.hpp

#include "my_class.hpp"

template<typename T, std::size_t First, std::size_t Second>
class other_class<T, First, Second, typename std::enable_if<condition>::type>{
    public:
        other_class(...){
            // ...
        }

        my_class<T, First> data[Second];
};

template<typename T, std::size_t Size>
template<std::size_t S, typename>
my_class<T, Size>::operator other_class<T, 1, Size>(){
    return other_class<T, 1, Size>(...);
}

一切顺利,直到我想定义转换运算符:/现在我在运算符的实现中收到关于不完整类型class my_class<T, Size>的错误。

这对我来说似乎很奇怪,因为我一直使用my_class作为other_class的数据就好了,这需要它完整(它调用类的默认构造函数)。 / p>

究竟是什么导致了错误?

系统是Ubuntu 14.04,带有GCC 4.8.2

1 个答案:

答案 0 :(得分:1)

您需要在转化运算符的定义中重复std::enable_if<condition>作为my class的第三个参数:

template<typename T, std::size_t Size>
template<std::size_t S, typename>
my_class<T, Size,    typename std::enable_if<condition>::type>::
                  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
operator other_class<T, 1, Size>(){
    // return ...
}

因此,只要my_class专门化,在同一condition下,就会实例化此定义。否则,您将进入my_class的主要模板,该模板未定义(因此不完整)。

使用虚拟条件,compiles in gcc/clang

修改

检查Understanding (simple?) C++ Partial Template Specialization,我现在意识到当my_class特化和转换运算符定义中的模板参数列表不完全匹配时,编译器会将后者解释为成员函数专门化对于一个不专门的类。这是不允许的。

我理解这一定是这种情况,因为我得到完全相同的编译器错误:

  • gcc:invalid use of incomplete type my_class<T, Size>
  • clang:nested name specifier 'my_class<T, Size>::' for declaration does not refer into a class, class template or class template partial specialization

(当然,这两条消息都没有用)。

这是reduced example重现错误:

template<typename T>
using enable = typename std::enable_if<sizeof(T)>=0>::type;

template<typename T, typename = void>
struct A;

template<typename T>
struct A<T, enable<T>>{ void f(); };

template<typename T>
void A<T, enable<T>>::  // compiles
// void A<T>::  // does not compile
f() { }

编辑2

我认为以下适用于iso 14.5.5.3/1:

14.5.5.3课程模板专业化的成员

  
      
  1. 类模板部分特化的成员的模板参数列表应与类模板部分特化的模板参数列表匹配。类模板部分特化的成员的模板参数列表应匹配类模板部分特化的模板参数列表。
  2.