gpt4 book ai didi

c++ - 是否可以使用 C++ 元编程收集一个特定模板的所有显式实例化类型?

转载 作者:行者123 更新时间:2023-12-02 10:22:48 26 4
gpt4 key购买 nike

我想实现一些编译时评估,包括将一个特定模板的所有显式实例化类型作为输入,就像这样:

template<typename T>
struct Box{T content;};

struct ExplicitlyInstantiatedBoxTypesHolder {
using types = SOME_MAGICAL_META_PRGRAMMING_CODE; // todo
};

template<typename...>
void printTypes();

template<>
void printTypes(){}

template<typename First, typename... Rest>
void printTypes(){
cout << typeid(First).name() << ", ";
printTypeNames<Rest...>();
}

int main(){
Box<int> box1;
Box<long> box2;

printTypes<ExplicitlyInstantiatedBoxTypesHolder::types...>();
// expected output:
// Box<int>, Box<long>
}

最佳答案

如果您只想保留(并打印)类型名称

您可以将创建的类型注册到静态“Regsitrar”中。

让我们为所有 Box 类型建立一个基础。该基地还将管理注册和打印:

class BoxBase {
private:
static std::set<std::string>& types() {
static std::set<std::string> types;
return types;
}
protected:
template<typename T>
static int registerType() {
std::string name = boost::typeindex::type_id<T>().pretty_name();
if(types().insert(name).second) {
// for the need of the line below see:
// https://stackoverflow.com/questions/59365123
static std::ios_base::Init force_init;
std::cout << "registering a box of type: " << name << std::endl;
}
return 0;
}
public:
static void print_types() {
for(const auto& type: types()) {
std::cout << type << ' ';
}
std::cout << std::endl;
}
};

现在类 Box 必须确保它为每个创建的类型注册自己:
template<typename T> class Box: public BoxBase {
const static int foo_;
public:
Box() {
std::cout << "creating a box of type: ";
std::cout << boost::typeindex::type_id<T>().pretty_name() << std::endl;
}
~Box() {
// we use foo_ here to avoid optimizing its initialization
std::cout << foo_ << std::endl;
}
void doSomething() const {}
};

template<typename T>
const int Box<T>::foo_ = BoxBase::registerType<T>();

现在将记录所有 Box 类型,无论它们创建的位置如何!
int main() {
std::cout << "-------------------------------" << std::endl;
std::cout << "box types: ";
BoxBase::print_types();
std::cout << "-------------------------------" << std::endl;

Box<long> long_box;
Box<int> int_box;

long_box.doSomething();
int_box.doSomething();

Box<long> long_box2;

Box<double> double_box;
}

void bar() {
Box<char> box;
}

输出:
registering a box of type: long
registering a box of type: int
registering a box of type: double
registering a box of type: char
-------------------------------
box types: char double int long
-------------------------------
creating a box of type: long
creating a box of type: int
creating a box of type: long
creating a box of type: double

代码:
http://coliru.stacked-crooked.com/a/c69162c8da91e51e

如果你真的想持有类型

您可以允许模板的用户提前声明可能使用的类型,然后只允许这些类型,并且您可以打印这些类型的列表。这也不完全是您要寻找的,但也许可以帮助解决相关问题。

这个想法是有一个工厂模板来管理允许的类型。

盒子工厂
template<typename... Ts> 
struct BoxesFactory {
template<typename T>
static Box<T> create_box() {
static_assert(TypeExists<T, Ts...>::value);
return Box<T>{};
}
static constexpr void print_types() {
TypesPrinter<Ts...>();
}
};

主要的
int main() {
BoxesFactory<int, long> factory;
std::cout << "Supported boxes: " << std::endl;
factory.print_types();

auto long_box = factory.create_box<long>();
auto int_box = factory.create_box<int>();
// auto double_box = factory.create_box<double>(); // <= compilation error

long_box.do_box_things();
int_box.do_box_things();
}

如果您想避免在工厂外部创建 Box,则可以在 BoxFactory 的私有(private)部分内声明类 Box 本身,或者您可以在 Box 的 ctor 中要求只有 BoxFactory 可以传递的私有(private) token 参数。

类型存在
template<typename Validate, typename T, typename... Ts>
struct TypeExists {
constexpr static bool value = TypeExists<Validate, T>::value
|| TypeExists<Validate, Ts...>::value;
};

template<typename Validate, typename T>
struct TypeExists<Validate, T> {
constexpr static bool value = std::is_same<Validate, T>::value;
};

类型打印机
template<typename T, typename... Ts>
struct TypesPrinter {
constexpr TypesPrinter() {
TypesPrinter<T>();
TypesPrinter<Ts...>();
}
};

template<typename T>
struct TypesPrinter<T> {
constexpr TypesPrinter() {
// std::cout << typeid(T).name() << ' ';
std::cout << boost::typeindex::type_id<T>().pretty_name() << ' ';
}
};

代码:
http://coliru.stacked-crooked.com/a/42f67cc6ce95e5c5

边注:
restricting the instantiation of a template to certain types 还有其他技术.但是那些不处理实际使用的类型的“簿记”。

关于c++ - 是否可以使用 C++ 元编程收集一个特定模板的所有显式实例化类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59358209/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com