c++ - 如何模拟静态类模板专业化的构造函数?
问题描述
如何模拟仅具有静态成员的类模板的构造函数并强制构造函数的特化?
我想实现一个模拟的“静态构造函数”,但使用类模板并且没有非专门的构造函数(函数模板)。这些函数必须被隐式调用(尽管必须小心处理)并且必须为每个类模板实例定义一个单独的函数。
此外,我想将 (1) 类的定义(以及构造函数仿真所需的所有其他内容)与 (2) 模板实例化和专门的“构造函数”定义分开。(1) 部分不应依赖于 (2)。
“构造函数”的操作可能只影响全局静态内存。
尝试 1“撕裂”
这是我到目前为止所拥有的:
#include <iostream>
using namespace std;
// -------------------- BEGIN PART (1)
template<int N> struct S
{
struct IS { };
static IS init();
static IS is;
static void foo() { cout << "foo called by S<" << N << ">" << endl; }
};
// -------------------- END PART (1)
// -------------------- BEGIN PART (2)
template<> S<1>::IS S<1>::init() // "constructor" specialized for "1"
{
cout << "init called by S<1>" << endl;
// do stuff specific to "1"
return {};
}
template<> S<3>::IS S<3>::init() // "constructor" specialized for "3"
{
cout << "init called by S<3>" << endl;
// do stuff specific to "3"
return {};
}
// -------------------- END PART (2)
// -------------------- BEGIN PART (1)
template<> S<1>::IS S<1>::is = init();
// -------------------- END PART (1)
int main()
{
cout << "Hello, Wandbox!" << endl;
S<3>::foo();
}
输出:
init called by S<1>
Hello, Wandbox!
foo called by S<3>
在这种情况下,我需要来自编译器/链接器的错误,告诉程序员S<3>::is
未定义。关键是要确保初始化没有被错误地忘记。
尝试2“订单问题”
在这里,类定义和特定用途是根据需要分开的。但它无法编译。
structure.hpp
template<int N> struct S
{
struct IS { };
static IS init();
static IS is;
};
template<> S<1>::IS S<1>::is = init();
template<> S<2>::IS S<2>::is = init();
main.cpp
#include <iostream>
#include "structure.hpp"
using namespace std;
template<> S<1>::IS S<1>::init() // "constructor" specialized for "1"
{
cout << "init called by S<1>" << endl;
// do stuff specific to "1"
return {};
}
template<> S<3>::IS S<3>::init() // "constructor" specialized for "3"
{
cout << "init called by S<3>" << endl;
// do stuff specific to "3"
return {};
}
int main()
{
cout << "Hello, Wandbox!" << endl;
}
编译错误:
error: specialization of 'static S<N>::IS S<N>::init() [with int N = 1]' after instantiation
5 | template<> S<1>::IS S<1>::init() // "constructor" specialized for "1"
| ^
解决方案
该解决方案使用非静态类模板作为(静态)类(模板)的容器,为其添加构造函数。该解决方案的缺点是:
- 原始(包含)类(模板)仍然可以在没有“构造函数”的情况下访问
- 访问函数不再是静态的。必须取消引用静态函数的地址 - 可能在运行时。
- 原始静态函数的访问必须通过成员来完成(难看的语法)
#include <iostream>
using namespace std;
//! adds a constructor to a static class
template<typename T>
struct Container
{
Container(); // no generic definition
T s; //!< non-static member of (static) class
};
template<int N>
struct S
{
static void foo()
{
cout << "foo " << N << endl;
}
};
using T1 = Container<S<42>>;
using T2 = Container<S<21>>;
// ---------- individual constructors for the contained classes
template<> T1::Container() { cout << "init 42" << endl; }
template<> T2::Container() { cout << "init 21" << endl; }
// ---------- object instantiation
T1 w1; // it does not matter if the object is
static T2 w2; // static or not
int main() {
std::cout << __cplusplus << std::endl;
w1.s.foo();
w2.s.foo();
}
特别是因为原始分类器仍然可以在不强制调用“构造函数”的情况下使用(在初始化时),所以这个解决方案并不令人满意。
推荐阅读
- javascript - date.value = new Date(date.value); 在 IE11 中不起作用
- sql - 根据 Amazon Redshift 中以下记录中的匹配值进行计数
- python - MATLAB的直方图均衡有什么问题?
- android-architecture-navigation - 如何关闭通过 Android Navigation 库启动的对话框片段
- php - 如何查看通过 PHP 上传到谷歌驱动器的文件?
- r - R 中的 Gmapsdistance 包错误“您必须使用 API 密钥来验证对 Google Maps Platform API 的每个请求。”
- python-3.x - 如何规范右偏数据
- jquery - 如何在动态创建的元素上触发按键事件
- c# - C# 以及在终结器中不能做什么
- php - php在上传之前将字符串变量添加到文件名的开头