编译时检查特征专长是否具有唯一ID [英] compile time check that trait specialization has unique id

查看:84
本文介绍了编译时检查特征专长是否具有唯一ID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看过很多文章,解释了如何为一个类生成唯一的ID。

I've seen many posts explaining how to generate a unique id for a class.

在我的情况下,ID由用户选择(出于各种原因) ),但我想确保在不同的类中两次都没有使用id。

In my case, the id is chosen by the user (for various reasons), but I want to make sure that no id is used twice in different classes.

我将问题简化为以下代码:

I reduced my problem to the following code :

struct A {}; struct B {};

template <typename T> struct traits {};
template <> struct traits<A> { static constexpr size_t id() { return 0; }}
template <> struct traits<B> { static constexpr size_t id() { return 1; }}

现在,是否有一种简单的方法可以确保某人没有添加专业化知识具有重复ID的特征:

Now, is there an easy way for me to make sure that someone does not add a specialization of the trait with a duplicated id :

struct C {};
template <> struct traits<C> { static constexpr size_t id() { return 1; // this should static_assert ! }}

我可以使用C ++ 11,但我不想滥用处理器。

I can use C++11, and I don't want to abuse the pre-processor.

如果可能的话,该解决方案不应要求专用于特征的代码中的任何特殊内容(即,如果可以通过查看已经存在的专业来从外部进行检查,会很棒。)

If possible, the solution should not require anything special from the code specializing the trait (i.e if the check can be done externally by looking at already existing specializations, it would be great).

谢谢

推荐答案

这是一个主意,我不确定它对您的适用性:

Here is one idea, which I am not sure how applicable it may be for you:

#include <cstddef>

struct A {}; struct B {}; struct C {};

template <size_t Id> constexpr size_t getId() { return Id; }

template <typename T> struct traits {};

template size_t getId<0>();
template <> struct traits<A> { static constexpr size_t id() { return getId<0>(); }};

template size_t getId<1>();
template <> struct traits<B> { static constexpr size_t id() { return getId<1>(); }};

/* This fails to compile
template size_t getId<1>();
template <> struct traits<C> { static constexpr size_t id() { return getId<1>(); }};
*/

int main() { return 0; }

这依赖于使用函数的显式模板实例化。显而易见的陷阱是,您可能会忘记添加此实例化并仍然使用该函数,然后它就不会失败。您可以定义一些预处理器宏以确保始终使用其定义特征。

This relies on using explicit template instantiation of a function. The pitfall, obviously, is that you may forget to add this instantiation and still use the function, and then it would not fail to compile. You could define some preprocessor macro to ensure traits are always defined with it.

编辑:正如 Oliv ,上述解决方案仅在所有模板实例化都发生在同一翻译单元中时才有效。此版本可在编译单元中使用,尽管它更容易出错(模板参数和返回值必须匹配)。

As pointed out by Oliv, the above solution only works when all template instantiations happen in the same translation unit. This version works across compilation units, although it is more prone to mistakes (template parameters and return values must match).

#include <cstddef>

struct A {}; struct B {}; struct C {};

template <size_t Id> constexpr size_t getId();

template <typename T> struct traits {};

template <> constexpr size_t getId<0>() { return 0; }
template <> struct traits<A> { static constexpr size_t id() { return getId<0>(); }};

template <> constexpr size_t getId<1>() { return 1; }
template <> struct traits<B> { static constexpr size_t id() { return getId<1>(); }};

/* This fails to compile
template <> constexpr size_t getId<1>() { return 1; }
template <> struct traits<C> { static constexpr size_t id() { return getId<1>(); }};
*/

int main() { return 0; }






编辑2:我发布了问题为什么显式模板实例化不会破坏ODR?,由于我在编写此答案时发现令人惊讶的行为。请参阅此处以获取有关编译失败的详细信息。


EDIT 2: I posted the question Why does explicit template instantiation not break ODR? due to a behavior I found surprising while writing this answer. See there for more detail on what may or may not fail to compile.

这篇关于编译时检查特征专长是否具有唯一ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆