【问题标题】:Using forward declaration in a template file with type guards在带有类型保护的模板文件中使用前向声明
【发布时间】:2018-09-04 21:19:24
【问题描述】:

我正在尝试将模板库中的前向声明与类型保护结合起来,以拦截错误类型的模板与错误类型的类一起使用的情况。这是我能理解的最简单的 sn-p 代码,以说明问题...

Main.cpp

#include <iostream>
#include "templates.h"

int main()
{
    B<int_array> hello;
    return 0;
}

模板.h

#include <type_traits>

#define USE_GUARD
#define FORWARD_DECLARE

template<typename T>
using is_pod = typename std::enable_if<std::is_pod<T>::value>::type;

typedef struct {
    int *p; 
    int n;   
} int_array;

template <typename E, typename T >
class A
{

};

#ifdef USE_GUARD
template <typename T, typename = is_pod<typename std::remove_pointer<decltype(T::p)>::type> >
#else
template <typename T>
#endif
class B : public T, public A< B<T>, T >
{                                     // This is the 'curiously recurring template
                                      // pattern' (CRTP)
public:
    //! Default constructor
    B() noexcept
    {
        T::p = nullptr;
        T::n = 0;
    }

#ifdef FORWARD_DECLARE
    void reorder(const int_array & newOrder);
#endif
};

template <typename T> class C : public B<T>
{
public:
    C() noexcept : B<T>()
    {
        T::p = nullptr;
        T::n = 0;
    }
};

#ifdef FORWARD_DECLARE
#ifdef USE_GUARD
template <typename T, typename = is_pod<typename std::remove_pointer<decltype(T::p)>::type> >
#else
template <typename T>
#endif
void B<T>::reorder(const int_array & newOrder)
{
    C<T> myC;
}
#endif

我收到如下错误消息:

Visual Studio 2015:

USE_GUARD 和 FORWARD_DECLARE 均未定义 - 工作正常

仅定义了 FORWARD_DECLARE - 工作正常

仅定义了 USE_GUARD - 工作正常

两者都已定义 - C3860: template argument lost following class template name must list parameters in the order used in template parameter list

g++:

USE_GUARD 和 FORWARD_DECLARE 均未定义 - 工作正常

仅定义了 FORWARD_DECLARE - 工作正常

仅定义了 USE_GUARD - 工作正常

两者都已定义 - Invalid use of incomplete type 'class B&lt;T&gt; 在定义函数“重新排序”的位置

因此,在将类型保护与前向声明相结合的方式上,显然我做错了一些事情,但是两个编译器都没有给我一个非常容易理解的错误消息。我是在语法上犯了一个基本错误,还是我只是想做一些根本上很愚蠢的事情?

【问题讨论】:

  • 此标头通过违反单一定义规则来要求未定义的行为。什么是“类型保护”,为什么不能在类模板的主体中放置一个静态断言?​​

标签: c++ templates types forward-declaration


【解决方案1】:

成员定义中不应重复默认参数,应提供所有参数:

#ifdef FORWARD_DECLARE
# ifdef USE_GUARD
template <typename T, typename U>
void B<T, U>::reorder(const int_array & newOrder)
# else
template <typename T>
void B<T>::reorder(const int_array & newOrder)
# endif
{
    C<T> myC;
}
#endif

Demo

【讨论】:

  • 是的,这就是答案;就那么简单。适用于两种编译器。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-28
  • 1970-01-01
相关资源
最近更新 更多