我试图使用构建一个未使用的变量的副作用,所以我不希望它被优化掉。
好的,我知道在构造变量时使用副作用可能不是一个好的做法。请允许我解释一下目前的情况。
我有一节抽象课和一节具体课。我已经建立了一个生产
Abstract*
指向具体类的指针。对于任何希望由抽象类生成的具体类,必须首先进行注册。以下是一个最小(非)工作示例:
// Abstract.hpp
#pragma once
class Abstract {
public:
virtual void Hello() const = 0;
};
// Abstract.cc
#include "Abstract.hpp"
#include "Factory.hpp"
template<>
Factory<Abstract>* Factory<Abstract>::_the_factory = nullptr;
// Concrete.hpp
#include "Abstract.hpp"
#include "iostream"
class Concrete : public Abstract {
public:
void Hello() const override {
std::cerr << "B" << std::endl;
}
};
// Concrete.cc
#include "Concrete.hpp"
#include "Factory.hpp"
const bool concrete_registered = Factory<Abstract>::GetInstance()->Register("concrete", []() {
return new Concrete;
});
// Factory.hpp
#pragma once
#include <map>
#include <string>
#include <functional>
#include <iostream>
template <class Product>
class Factory {
public:
using ProductCreator = std::function<Product*()>;
static Factory* GetInstance() {
if (!_the_factory) {
_the_factory = new Factory;
}
return _the_factory;
}
bool Register(const std::string& name, const ProductCreator& creator) {
bool result = _creator_map.insert(std::make_pair(name, creator)).second;
if (result) {
std::cerr << name << " registered" << std::endl;
} else {
std::cerr << name << " can't be registered" << std::endl;
}
return result;
}
Product* GetProduct(const std::string& name) {
if (_creator_map.find(name) == _creator_map.end()) {
std::cerr << "Unknown product name " << name << " detected";
}
return _creator_map[name]();
}
private:
static Factory* _the_factory;
std::map<std::string, ProductCreator> _creator_map;
};
我希望,通过制作
concrete_registered
一个常量,我可以强制程序在之前执行注册代码
main
这样我就可以得到的产品
Concrete
来自工厂。以下是我如何使用它们:
// main.cc
#include "Abstract.hpp"
#include "Factory.hpp"
int main() {
auto ptr = Factory<Abstract>::GetInstance()->GetProduct("concrete");
ptr->Hello();
}
整个项目的结构如下:
âââ CMakeLists.txt
âââ lib
â âââ Abstract.cc
â âââ Abstract.hpp
â âââ CMakeLists.txt
â âââ Concrete.cc
â âââ Concrete.hpp
â âââ Factory.hpp
âââ main.cc
还有我的
CMakeLists.txt
是:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(test)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_subdirectory(lib)
add_executable(main main.cc)
target_link_libraries(main lib)
# lib/CMakeLists.txt
add_library(lib Abstract.cc Concrete.cc)
target_include_directories(lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
但是,我在运行程序时出现了以下错误:
terminate called after throwing an instance of 'std::bad_function_call'
事实上,我没有看到显示成功注册的日志
混凝土
对象(注意登录
Factory.hpp
)
在花了一些时间搜索这个问题后,我意识到这可能是变量的结果
混凝土注册
未使用,因此链接器不会将其链接到主程序。这就是为什么我需要使用为未使用的变量构造的副作用。
我的问题是:是否可以强制C++链接器链接
混凝土注册
到主程序?我知道一些技巧,比如
-Wl,--whole-archive -lXXX -Wl,--no-whole-archive
但我担心链接整个目标可能太多了,我只需要这部分代码“没有优化”