【问题标题】:Prevent all instantiations of a template class - including supported types阻止模板类的所有实例化 - 包括支持的类型
【发布时间】:2014-10-28 23:46:51
【问题描述】:

如果我有一个模板类 MyClass<T> 并且如果我显式实例化 intfloat(在 cpp 文件中),那么我可以使用 extern template class MyClass<int>extern template class MyClass<float> 来防止遇到任何编译单元这个类不必要地为intfloat 实例化它。当然,对于任何其他类型,该类仍然会被实例化。

现在我有一个 MyClass2<T> 类,它仅适用于 intfloatchardoubleshort 及其未签名的变体(如果适用)。因为我事先知道所有的类型,所以这个类中所有方法的定义都在cpp文件中。这也是我为所有上述类型显式实例化MyClass2<T> 的地方。在标题中,我有 static_assert 阻止用户使用不受支持的类型创建 MyClass2<T>

有没有办法完全阻止 MyClass2<T> 对所有类型(包括支持的类型)进行实例化(例如 extern template class MyClass2;,尽管我知道这不起作用)?像extern template全部?我想避免为所有支持的类型输入extern template class MyClass2<int>

考虑到我已经为这些类型显式地实例化了类,这似乎不仅是多余的,而且对于大型项目(比如我正在处理的项目)来说,每次添加新类型时我还需要维护另外几行代码。

【问题讨论】:

  • 我们的代码是跨平台的,所以MSVC++ 2010-2013CLang in XCode 6GCC

标签: c++ templates extern explicit-instantiation


【解决方案1】:

这听起来确实像是宏的工作:

// explicit_instantiations.h
#ifndef PERFORM_INSTANTIANTION
#define EXTERNALLY_INSTANTIATED extern
#else
#define EXTERNALLY_INSTANTIATED
#endif

EXTERNALLY_INSTANTIATED template class MyClass<int>;
EXTERNALLY_INSTANTIATED template class MyClass<float>;
// etc.

// header
#include "explicit_instantiations.h"

// cpp file
#define PERFORM_INSTANTIATION
#include "explicit_instantiations.h"

【讨论】:

  • 这根本不是一个坏主意。我会有额外的文件,但可维护性会弥补它。太棒了。
【解决方案2】:

你可以像下面这样使用 SFINAE

template<typename T>
using value_type =  typename std::enable_if<
                    std::is_same<float, T>::value ||
                    std::is_same<double, T>::value
                    //...other supported types goes here
                   >::type  ;



template<class T, class Enable = void>
class  MyClass2 ;

template<class T>
class MyClass2<T, value_type<T> > 
{
};

 MyClass2<float> t;
 MyClass2<int> t1; // Error !

Here

【讨论】:

  • @Barry 为什么只有value_type&lt;T&gt;
  • 所以是双重的。我认为要么将typename 放在enable_if 前面(你不需要),或者在它的末尾添加::type,这样你就可以把它放在MyClass2 中。就个人而言,我喜欢使用模板别名主要是为了避免到处都有typename X::type cruft...
  • 我已经在使用static_assert 来避免实例化不受支持的类型。那不是问题。问题是所有支持的类型都被所有编译单元多次编译,编译时间膨胀。我想知道extern template class 是否有一个包罗万象的方法,以避免实例化所有类型,包括不受支持的类型,因为这些类型是在它们各自的cpp 文件中实例化的。
  • @T.C.我认为他的意思是SFINAE替换失败不是错误
  • @Samaursa 我仍然没有得到extern template class 的“全能”问题?
【解决方案3】:

怎么样:

template <typename T>
struct Base {};

template <typename T> 
struct Supported;

template <> 
struct Supported<int> : public Base<int>
{};

【讨论】:

  • 这解决了一个问题,但打开了更多问题。现在我有一个充满这些类的标题(没关系),我将不得不重新定义所有构造函数。最大的问题是,每次内部支持新类型(并显式实例化)时,我都必须更改标头。对于每一种新类型,我都必须这样做,这又是更多的维护。在这种情况下,我宁愿输入extern template class :)
  • 您需要更改标头才能获取所有编译时间信息。否则,该类型是运行时类型(boost::any),您可能会避免。
猜你喜欢
  • 1970-01-01
  • 2017-12-02
  • 1970-01-01
  • 2017-11-21
  • 1970-01-01
  • 1970-01-01
  • 2014-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多