我在几个不同的地方读过,使用C++ 11的新字符串文字,可以在编译时计算字符串的哈希值.然而,似乎没有人准备出来说它将是可能的或如何完成.
我特别感兴趣的是这样的用例.
void foo( const std::string& value )
{
switch( std::hash(value) )
{
case "one"_hash: one(); break;
case "two"_hash: two(); break;
/*many more cases*/
default: other(); break;
}
}
Run Code Online (Sandbox Code Playgroud)
注意:编译时哈希函数不必像我编写的那样完全.我尽力猜测最终解决方案的样子,但meta_hash<"string"_meta>::value也可能是一个可行的解决方案.
出于内省的目的,有时我想自动为类型或类似的东西分配序列号.
不幸的是,模板元编程本质上是一种功能语言,因此缺乏实现这种计数器的全局变量或可修改状态.
或者是吗?
按请求的示例代码:
#include <iostream>
int const a = counter_read;
counter_inc;
counter_inc;
counter_inc;
counter_inc;
counter_inc;
int const b = counter_read;
int main() {
std::cout << a << ' ' << b << '\n'; // print "0 5"
counter_inc_t();
counter_inc_t();
counter_inc_t();
std::cout << counter_read << '\n'; // print "8"
struct {
counter_inc_t d1;
char x[ counter_read ];
counter_inc_t d2;
char y[ counter_read ];
} ls;
std::cout << sizeof ls.x << ' ' << sizeof ls.y << '\n'; // print "9 …Run Code Online (Sandbox Code Playgroud) 我希望创建一个std::type_index不需要RTTI的替代方案:
template <typename T>
int* type_id() {
static int x;
return &x;
}
Run Code Online (Sandbox Code Playgroud)
请注意,局部变量的地址x用作类型ID,而不是其x自身的值.另外,我不打算在现实中使用裸指针.我刚刚删除了与我的问题无关的所有内容.在这里查看我的实际type_index实现.
这种方法听起来是否合理,如果是这样,为什么?如果没有,为什么不呢?我觉得我在这里不稳定,所以我对我的方法将会或不会起作用的确切原因感兴趣.
典型的用例可能是在运行时注册例程以通过单个接口处理不同类型的对象:
class processor {
public:
template <typename T, typename Handler>
void register_handler(Handler handler) {
handlers[type_id<T>()] = [handler](void const* v) {
handler(*static_cast<T const*>(v));
};
}
template <typename T>
void process(T const& t) {
auto it = handlers.find(type_id<T>());
if (it != handlers.end()) {
it->second(&t);
} else {
throw std::runtime_error("handler not registered");
}
}
private:
std::map<int*, …Run Code Online (Sandbox Code Playgroud) 为什么静态数据成员初始化必须在类之外?
class X
{
public:
int normalValue = 5; //NSDMI
static int i;
};
int X::i = 0;
Run Code Online (Sandbox Code Playgroud)
为什么静态数据成员(此处为"i")只是一个声明,而不是一个定义?
早上好,伙计们!
我正在重构一个事件队列.我正在四处寻找,看看我是否可以在编译时使事件ID独特.我提出的与clang 4.0.0一起工作,但是给出了g ++ 6.3.1的编译错误.
我们的想法是使用静态成员变量的地址来唯一标识各个类型,然后使用标记从类模板生成这些唯一类型.
使用静态成员的地址作为类型id是一种相当常见的技术,但使用模板来实现它意味着要清除ODR.MSN引用此标准来表明这是一种有效的方法: 编译时常量id
我的问题是做这个constexpr.如果我删除constexpr并在运行时测试它,一切都按预期工作.但是,执行此constexpr会导致g ++中的静态断言失败,"错误:静态断言的非常量条件".
经过相当多的研究,似乎最相似的问题是:
大多数这些问题都是g ++不合格和clang ++错误输出.这是相反的.
我很难过.这是我所获得的精简版本,注释了静态断言中不能用g ++编译的内容:
template <typename tag>
struct t
{
constexpr static char const storage{};
};
template <typename tag>
constexpr char const t<tag>::storage;
struct tag_0 {};
struct tag_1 {};
static_assert(&t<tag_0>::storage == &t<tag_0>::storage, "This always compiles.");
static_assert(&t<tag_1>::storage == &t<tag_1>::storage, "So does this.");
static_assert(&t<tag_0>::storage != &t<tag_1>::storage, "This does not compile with g++.");
static_assert(!(&t<tag_0>::storage == &t<tag_1>::storage), "Neither does this.");
constexpr auto …Run Code Online (Sandbox Code Playgroud) 标准是否规定调用std::type_index(typeid(obj))将是该类型的唯一?我找不到相关信息.从type_info::name()我得到这个:
返回包含类型名称的实现定义的以null结尾的字符串.不给出任何保证,特别是返回的字符串对于几种类型可以是相同的,并且在相同程序的调用之间改变.
(来源:http://en.cppreference.com/w/cpp/types/type_info/name)
这使我相信,也许是错位的名称/ typeids是不是一定是唯一的.然而,该页面std::type_index专门用于假设这些类型在其" 使用示例 "中是唯一的.
那么我怎么知道typeid我的编译器是否是唯一的,以及碰撞的可能性是什么?此外,有什么方法可以获得我们可以知道的某种类型的标识符(无论是字符串还是其他类型)?
Demangling是不是一种选择,因为它是非常大的类型太慢了,但我的猜测是,如果实现提供了一个工具来还原函数的名称,然后将错位的名称应该是该类型在实施独特的,无论如何,正确吗?
为什么这样做?
我看到类似的SO问题说它确实如此,但有人可以更详细地解释它吗?特别是,这种行为是否受到标准的保护?
IH
#ifndef I_H_
#define I_H_
typedef void (*FuncPtr)();
template<typename T>
void FuncTemplate() {}
class C {};
#endif
Run Code Online (Sandbox Code Playgroud)
a.cc
#include "i.h"
FuncPtr a() {
return &FuncTemplate<C>;
}
Run Code Online (Sandbox Code Playgroud)
b.cc
#include "i.h"
FuncPtr b() {
return &FuncTemplate<C>;
}
Run Code Online (Sandbox Code Playgroud)
m.cc
#include <iostream>
#include "i.h"
FuncPtr a();
FuncPtr b();
int main() {
std::cout << (a() == b() ? "equal" : "not equal") << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后
$ g++ -c -o a.o a.cc
$ g++ -c -o b.o b.cc
$ g++ -c …Run Code Online (Sandbox Code Playgroud) 我在一本用于在编译时创建 SDBM 哈希值的书中找到了这个示例/类。不幸的是它无法编译(无论是 c++11 还是 c++14)。我正进入(状态error: call to non-constexpr function。我尝试了一下,但似乎无法完成这项工作。所以这是我的问题:
完整(不起作用)示例供您测试:
#include <iostream>
template <int stringLength>
struct SDBMCalculator
{
static inline int Calculate(const char* const stringToHash, int& value)
{
int character = SDBMCalculator<stringLength - 1>::Calculate(stringToHash, value);
value = character + (value << 6) + (value << 16) - value;
std::cout << static_cast<char>(character) << std::endl << value << std::endl << std::endl;
return stringToHash[stringLength - 1];
}
static inline int CalculateValue(const char* const stringToHash)
{
int value = 0; …Run Code Online (Sandbox Code Playgroud) 在下面的代码中,我将地址分配给静态 constexpr 成员:
struct component_type_data{};
template<class Derived>
class component{
private:
const constexpr static component_type_data type_data{};
public:
static constexpr const component_type_data* component_type = &type_data;
};
Run Code Online (Sandbox Code Playgroud)
我的动机是让编译时类型有唯一的 id。
这是有效的吗?代码仅从 C++17 开始编译。我可以使用该指针作为模板参数。
如果这有效,编译器如何预先知道地址?
更新 :
另外,跨 dll 边界会发生什么?每个 dll 对于相同的静态成员都有自己唯一的地址,或者它们将是相同的?