如果模板尚未使用某种类型实例化,是否可能会触发编译器/链接器错误?

2024-02-19

后续问题[转换为指向模板的指针是否会实例化该模板?] https://stackoverflow.com/questions/8379002/does-a-casting-to-a-pointer-to-a-template-instantiate-that-template.

问题正如标题所说,剩下的问题是类模板的约束和使用示例,以及我为实现目标所做的尝试。

一个重要的约束:用户通过子类化我的类模板来实例化模板(而不是像我下面的尝试那样显式实例化它)。因此,对我来说重要的是,如果可能的话,用户不需要做任何额外的工作。只需子类化就应该可以工作(子类实际上已经在字典中注册了自己,除了使用 CRTP 对附加类模板进行子类化之外,用户无需执行任何操作,并且子类永远不会被创建它的用户直接使用)。如果确实没有其他方法,我愿意接受用户需要做额外工作的答案(例如从额外的基础派生)。


解释如何使用类模板的代码片段:

// the class template in question
template<class Resource>
struct loader
{
  typedef Resource res_type;
  virtual res_type load(std::string const& path) const = 0;
  virtual void unload(res_type const& res) const = 0;
};

template<class Resource, class Derived>
struct implement_loader
  : loader<Resource>
  , auto_register_in_dict<Derived>
{
};

template<class Resource>
Resource load(std::string const& path){
  // error should be triggered here
  check_loader_instantiated_with<Resource>();

  // search through resource cache
  // ...

  // if not yet loaded, load from disk
  // loader_dict is a mapping from strings (the file extension) to loader pointers
  auto loader_dict = get_all_loaders_for<Resource>();
  auto loader_it = loader_dict.find(get_extension(path))
  if(loader_it != loader_dict.end())
    return (*loader_it)->load(path);
  // if not found, throw some exception saying that
  // no loader for that specific file extension was found
}

// the above code comes from my library, the code below is from the user

struct some_loader
  : the_lib::implement_loader<my_fancy_struct, some_loader>
{
  // to be called during registration of the loader
  static std::string extension(){ return "mfs"; }
  // override the functions and load the resource
};

现在以表格形式:

  • 用户来电the_lib::load<my_fancy_struct>带有资源路径
  • Inside the_lib::load<my_fancy_struct>,如果路径标识的资源尚未缓存,我从磁盘加载它
  • 具体的loader在这种情况下使用的是在启动时创建并保存在字典中
  • 每个资源类型都有一个字典,它们映射[文件扩展名 ->loader指针]
  • If the dictionary is empty, the user either
    • 没有为该特定扩展创建加载程序或
    • 没有为该特定资源创建加载程序
  • 我只希望第一种情况让我抛出运行时异常
  • 第二种情况应该在编译/链接时检测,因为它涉及模板

理由:我非常赞成早期错误,如果可能的话,我希望在运行时(即编译和链接时)之前检测到尽可能多的错误。由于检查该资源的加载器是否存在只涉及模板,因此我希望可以做到这一点。


我尝试的目标:在调用时触发链接器错误check_error<char>.

// invoke with -std=c++0x on Clang and GCC, MSVC10+ already does this implicitly
#include <type_traits>

// the second parameter is for overload resolution in the first test
// literal '0' converts to as well to 'void*' as to 'foo<T>*'
// but it converts better to 'int' than to 'long'
template<class T>
void check_error(void*, long = 0);

template<class T>
struct foo{
  template<class U>
  friend typename std::enable_if<
    std::is_same<T,U>::value
  >::type check_error(foo<T>*, int = 0){}
};

template struct foo<int>;

void test();

int main(){ test(); }

鉴于上面的代码,以下test定义确实实现了 MSVC、GCC 4.4.5 和海湾合作委员会4.5.1 http://ideone.com/7FRrU:

void test(){
  check_error<int>(0, 0); // no linker error
  check_error<char>(0, 0); // linker error for this call
}

但是,它不应该这样做,因为传递空指针不会触发 ADL。为什么需要 ADL?因为标准是这么说的:

§7.3.1.2 [namespace.memdef] p3

[...] 如果一个friend非局部类中的声明首先声明一个类或函数,友元类或函数是最内层封闭命名空间的成员。在该命名空间范围内提供匹配的声明之前,通过非限定查找或限定查找都找不到好友的名称(在授予友谊的类定义之前或之后)。 [...]

通过强制转换触发 ADL,如以下定义所示test,在 Clang 3.1 和 GCC 4.4.5 上实现了目标,但是GCC 4.5.1 已经链接良好 http://ideone.com/0kAMz,与 MSVC10 一样:

void test(){
  check_error<int>((foo<int>*)0);
  check_error<char>((foo<char>*)0);
}

遗憾的是,GCC 4.5.1 和 MSVC10 在这里具有正确的行为,正如链接问题中所讨论的,特别是这个答案 https://stackoverflow.com/a/8383216/500104.


每当引用模板函数并且模板的完整规范可用时,编译器都会实例化模板函数。如果没有可用的,编译器不会并希望其他翻译单元能够实例化它。例如,基类的默认构造函数也是如此。

文件头.h:

template<class T>
class Base
{
public:
   Base();
};

#ifndef OMIT_CONSTR
template<class T>
Base<T>::Base() { }
#endif

文件client.cc:

#include "header.h"

class MyClass : public Base<int>
{
};


int main()
{
   MyClass a;
   Base<double> b;
}

文件检查.cc:

#define OMIT_CONSTR
#include "header.h"

void checks()
{
   Base<int> a;
   Base<float> b;
}

Then:

 $ g++ client.cc check.cc
/tmp/cc4X95rY.o: In function `checks()':
check.cc:(.text+0x1c): undefined reference to `Base<float>::Base()'
collect2: ld returned 1 exit status

编辑: (尝试将其应用到具体示例中)

我将这个文件命名为“loader.h”:

template<class Resource>
struct loader{
  typedef Resource res_type;
  virtual res_type load(std::string const& path) const = 0;
  virtual void unload(res_type const& res) const = 0;

  loader();
};

template<class Resource>
class check_loader_instantiated_with : public loader<Resource> {
  virtual Resource load(std::string const& path) const { throw 42; }
  virtual void unload(Resource const& res) const { }
};

template<class Resource>
Resource load(std::string const& path){
  // error should be triggered here
  check_loader_instantiated_with<Resource> checker;
  // ...
}

另一个文件“loader_impl.h”:

#include "loader.h"
template<class Resource>
loader<Resource>::loader() { }

据我所知,该解决方案有一个弱点。每个编译单元都可以选择仅包含 loader.h 或 loader_impl.h。您只能在包含 loader_impl 的编译单元中定义加载器,并且在这些编译单元中,所有加载器都禁用错误检查。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果模板尚未使用某种类型实例化,是否可能会触发编译器/链接器错误? 的相关文章

随机推荐

  • 有可用的 FreeRTOS 解释语言库吗?

    我在一家公司工作 该公司使用 FreeRTOS 为多个设备创建固件 最近 我们对新功能的要求已经超出了我们固件工程师的工作能力 但我们现在也无力雇用任何新人 即使进行微小的更改 也需要固件人员在非常低的级别上进行修改 我一直在为 FreeR
  • 如何使用textview.getLayout()?它返回空值

    我正在尝试设置布局textview所以我可以用getEllipsisCount 方法 但下面的代码返回 null 作为布局值 我如何进行布局然后使用getEllipsisCount 0 method public class MainAct
  • Matlab中使用滑块旋转图像

    我在 Matlab 中有一个 GUI 使用 GUIDE 它看起来是这样的 我想使用滑块旋转图像并实时显示变化 我使用轴来显示图像 我怎样才能做到这一点 EDIT 我正在构建 OCR 应用程序 这就是我旋转盘子时的样子 数字完全变形了 tha
  • Mac osx 10.9.2 上的 mysql-python:错误:命令“/usr/bin/clang”失败,退出状态为 1

    我想将我的 django 应用程序从 sqlite 移植到 mysql 但是当我尝试安装 mysql python 时 它给了我这个错误 错误 命令 usr bin clang 失败 退出状态为 1 我四处寻找线索并尝试了这个似乎对大多数人
  • 如何将数据从控制器传递到 ASP.net MVC 中的视图? [复制]

    这个问题在这里已经有答案了 net MVC 我需要做的事情对于我认识的每个人来说都很简单 我需要在控制器之间传递数据以在 ASP net MVC 中查看 我在控制器中编写的代码 public ActionResult Upload View
  • Bundler 未加载 gem

    我在使用 Bundler 和能够访问我的宝石而不需要在某个地方需要它们时遇到了问题 因为config gem曾经为我这样做过 据我所知 在我的 Rails 3 应用程序中 我定义了我的Gemfile像这样 clear sources sou
  • 如何用按钮更新闪亮的数据表

    我试图在用户按下 Shiny 中的按钮后简单地更新数据框的列 我对当前显示的数据帧如何传递到服务器端函数有点困惑 一旦按下按钮 列 cyl 应增加 10 如果再次按下按钮 列应采用重新计算的值并再乘以 10 依此类推 到目前为止 我已经做到
  • 如何使用 Javascript 从 JSON 文件中选择随机对象(?)?

    在我正在制作的 Discord Bot 中 它需要从 JSON 文件中选择一个随机对象 我当前的代码是这样的 function spawn if randomNum 24 return const name names randomNum
  • UISearchBar 范围栏位置?

    我在使用 iPad 应用程序 我想知道是否可以将范围栏从 UISearchBar 的右侧移动到另一个位置 我希望将范围栏放在搜索栏下方 那可能吗 提前致谢 好的 这是我的解决方案 我将实现我自己的分段控件来创建搜索范围的可能性 let ca
  • 反应本机本地通知

    我是 React Native 的新手 需要实现一个功能 应用程序需要每天在特定时间向用户发送通知 每天要显示的数据存储在客户端的json文件中 不会改变 通知已按计划进行 鉴于我希望有一种方法可以从应用程序本身触发通知 有谁知道无需将应用
  • 访问相机和照片库

    在我的 iOS 应用程序中 我有一个 ImageView 和两个用于打开相机和照片库的按钮 当我单击其中一个按钮时 应用程序将关闭 我在我的设备上运行应用程序 而不是模拟器 我的代码需要更改什么 class PhotoViewControl
  • 保留 std::set 或 std::unordered_set 上的插入顺序

    在将其标记为重复之前 我已经here https stackoverflow com questions 1098175 a stdmap that keep track of the order of insertion here htt
  • PDO bindColumn 和 PDO::FETCH_BOUND —— 强制还是可选?

    在我们的 PHP 代码的许多地方 如果重要的话可以使用 postgres 我们有这样的东西 q SELECT DISTINCT a id FROM alarms current a entities e installations i q
  • jQuery AJAX 响应设置 Cookie 标头

    我有一个使用 REST API 的项目 在这里 当我发送登录请求时 他们会以包含一些数据的 JSON 形式向我发送响应 与响应标头中的内容一起 Access Control Allow Origin Connection keep aliv
  • 在不同的元素上使用相同的控制器来引用同一个对象

    我想如果我打了一巴掌ng controller GeneralInfoCtrl 在我的 DOM 中的多个元素上 它们会共享相同的内容 scope 或者至少双向绑定不起作用 我想要这样做的原因是因为我在 HTML 的不同部分有不同的只读视图和
  • SVG 不从父级继承值

    所以这似乎是一个错误今天出现在 Chrome 中 显然还有 Firefox 我有一个 SVG 包裹在一个跨度内 我也尝试过 div 和对象标签 这似乎并不重要 并且该跨度具有指定的高度和宽度 昨天 子元素会根据其父元素的完整尺寸适当调整自身
  • 是否有一种算法可以从数组中提取二重奏中的值并对它们进行操作? [复制]

    这个问题在这里已经有答案了 我有一个像这样的数组 1 2 3 4 5 6 7 8 9 我想在二重唱中获得这样的项目 1 2 做一些操作 2 3 做一些操作 3 4 做一些操作 4 5 做一些操作 5 6 做一些操作 6 7 做一些操作 7
  • 从 Samsung Tizen TV 应用程序启动 AppStore

    我正在尝试在基于 Javascript 的 Tizen TV 应用程序中实现一个按钮 单击该按钮后 它应该打开另一个应用程序的 App Store 页面 我指的是这些文件 https developer tizen org sites de
  • UIWebView 日志消息 iOS 7 [重复]

    这个问题在这里已经有答案了 我正在开发一个使用网络浏览器的应用程序 在构建它后我收到了以下消息 UITextField webView called This method is no longer supported with the n
  • 如果模板尚未使用某种类型实例化,是否可能会触发编译器/链接器错误?

    后续问题 转换为指向模板的指针是否会实例化该模板 https stackoverflow com questions 8379002 does a casting to a pointer to a template instantiate