我想在编译时实现 atoi() 函数(在 C++ 语言中,使用 C++11 或 C++14 标准)。所以它应该能够将双引号括起来的文本解析为数字,或者报告错误。更具体地说,它是更大系统的一部分,能够在编译时解析类似 printf 的格式。而且我想在单词上拆分格式字符串,如果某些特定单词可以用数字表示 - 输出数字而不是字符串(在场景后面是序列化器类,它可以比字符串更有效地序列化数字,哪个更重要的是,反序列化器不应该尝试将每个字符串解析为数字,因为格式字符串中打印的所有数字始终表示为数字,而不是字符串)...
据我所知,有两种方法可以解决任务:
1) 通过使用 constexpr 函数;
2)通过模板元编程。
哪种方式可以更好?我尝试了第一种方式,我可以看到这种方式存在很多障碍:尤其是与 c++11 相关的限制很少。看起来第二个可能更可取,但它需要一些技巧(您需要使用运算符“”来拆分 c 字符串以分隔字符,这在从 c++14 开始的 gcc 和从 c++11 开始的 clangs 中支持)。此外,完全基于 TMP 的解决方案可能太大且太纠结。
以下是我的解决方案,我很高兴听到一些关于它的建议。
http://coliru.stacked-crooked.com/a/0b8f1fae9d9b714b
#include <stdio.h>
template <typename T> struct Result
{
T value;
bool valid;
constexpr Result(T v) : value(v), valid(true) {}
constexpr Result() : value(), valid(false) {}
};
template <typename T>
constexpr Result<T> _atoi_oct(const char *s, size_t n, T val, int sign)
{
return n == …
Run Code Online (Sandbox Code Playgroud) c++ compile-time-constant compile-time template-meta-programming c++11
我有两个类和接口(例如DatabaseModel
,LocalStore
和InternalModelInterface).它们的定义如下;
public class DatabaseModel {
// ...
public static final String KEY_PARAM1 = "param1";
}
public class LocalStore implements InternalModelInterface {
// ...
public void function () {
String temp = InternalModelInterface.COLUMN_PARAM1;
}
}
public interface InternalModelInterface {
public static final String COLUMN_PARAM1 = DatabaseModel.KEY_PARAM1;
// ...
}
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是,在运行时,当我调用时localStore.function()
,temp被赋值为null,因为InternalModelInterface.COLUMN_PARAM1
为null.这有意义吗?不InternalModelInterface.COLUMN_PARAM1
应该在编译时进行评估并内联?
这适用于Android应用程序.提前致谢.
我将进一步解释澄清任何混淆.
在DatabaseModel
解析JSON响应时实例化该类的对象.DatabaseModel
类中定义的常量表示在JSON响应中查找的键.
的InternalModelInterface
定义了在设备上的本地(缓存)数据库中使用的列名.由于多种原因(包括它们是SQLite中的非法列名),我不会将键重用为列名.
我使用接口而不仅仅是普通类的原因是接口还指定了需要由第三类LocalStore实现的所需方法.
这个问题纯粹来自"心理大师",可能没有实际价值.
如果我在Clojure中定义一个值def
,是否可以诱导编译器在编译时对其进行评估,而不是等到运行时?
(def the-answer 42)
(+ the-answer 1)
Run Code Online (Sandbox Code Playgroud)
我想我可以定义一个宏,但调用语法变得有点尴尬:
(defmacro the-answer [] 42)
(+ (the-answer) 1)
Run Code Online (Sandbox Code Playgroud)
这也有效,但仍然很难看:
(+ `~the-answer 1)
Run Code Online (Sandbox Code Playgroud)
我也理解(或相信)Clojure在编译时评估常量表达式:
(def milliseconds-per-day (* 24 60 60 1000))
Run Code Online (Sandbox Code Playgroud)
我只是在学习Common Lisp,但我的理解是Common Lisp支持用户定义的阅读器宏,所以你可以定义一个阅读器宏(类似的东西#$
),它在编译时评估下面的符号:
(+ #$the-answer 1)
Run Code Online (Sandbox Code Playgroud)
顺便说一句,该语法并不比宏调用"更漂亮".
如何让Clojure在编译时评估常量变量并用实际值替换引用?它已经这样做了吗?
在任何人开始引用Knuth定律之前("过早优化是所有邪恶的根源"),我要求这个问题更好地理解Clojure编译的内部.
class Foo {
final val pi = 3
}
Run Code Online (Sandbox Code Playgroud)
每个Foo
对象都有pi
会员吗?我应该放入pi
伴侣物体吗?
scala final constants compile-time-constant companion-object
我有一个用户定义的文字运算符,它只对特定长度的字符串有意义,如下所示:
constexpr uint16_t operator "" _int(const char* s, std::size_t len)
{
return len == 2 ? s[0] | (s[1] << 8) : throw;
}
Run Code Online (Sandbox Code Playgroud)
这有效:
"AB"_int // equals 16961
Run Code Online (Sandbox Code Playgroud)
但这也可以编译,我不希望它:
"ABC"_int // throws at runtime
Run Code Online (Sandbox Code Playgroud)
我试过了static_assert(len == 2)
,但在 constexpr 函数中是不允许的。
如何"ABC"_int
在编译时导致错误?
c++ static-assert compile-time-constant user-defined-literals c++11
视觉C++有#pragma message
其输出一个字符串到编译器输出.现在我有一家工厂:
template<class Type>
CComPtr<Type> CreateComObject()
{
CComPtr<Type> newObject( new CComObject<Type> );
//do some tuning to the object
return newObject;
}
Run Code Online (Sandbox Code Playgroud)
我想输出传递给的类的大小new
(即sizeof( CComObject<Type> )
输入编译器输出.看起来#pragma message
只接受字符串.
如何输出编译时数字常量?
我有一个 C 库,它需要明确定义字符串长度的字符串类型:
#[repr(C)]
pub struct FFIStr {
len: usize,
data: *const u8,
}
Run Code Online (Sandbox Code Playgroud)
因为这种类型被用作静态类型,所以我想要一种使用 const 函数或宏(而不是手动设置len
)安全地声明它的方法。
我的第一次尝试是使用宏len()
,但是在1.39.0 之前的版本中,不可能将切片的长度作为 const fn 获取:
macro_rules! ffi_string {
($x:expr) => {
FFIStr { len: $x.len(), data: $x as *const u8 }
};
}
#[no_mangle]
pub static mut HELLO_WORLD: FFIStr = ffi_string!(b"Hello, world!");
Run Code Online (Sandbox Code Playgroud)
error: core::slice::<impl [T]>::len` is not yet stable as a const function
我的第二次尝试是使用std::mem::size_of<T>
,但似乎没有办法在不使用泛型的情况下获取静态数组的类型:
const fn ffi_string<T>(s: &'static T) -> FFIStr …
Run Code Online (Sandbox Code Playgroud) 尽管阅读了一些 StackOverflow 帖子(this和this)和 cppreference 页面,但我无法弄清楚非静态局部变量与非静态局部变量 相比有何constexpr
好处。 static constexpr
我能看到的唯一区别是每个调用都有自己的实例,但由于它是一个constexpr
我在这里看不到实际优势(因为,如果我理解正确,这会导致每个实例都是相同且不可变的,使得多个实例只是多余的)。
或者,从另一个角度争论:由于非静态constexpr
局部变量在(每次)函数调用时初始化,因此简单局部变量没有任何优势const
,尽管它可以用于编译时评估。但是,当编译时评估需要它们时,没有必要将它们设置为非静态的。
所以我的问题是:我的论点有什么缺陷,在什么情况下非静态constexpr
局部变量是合理的并且可能是最佳选择?
我一直试图了解静态变量是如何初始化的。并注意到cppref和 enseignement处常量初始化和零初始化的顺序存在矛盾。
在cppref上它说:
常量初始化是在所有其他初始化之前执行的,而不是静态和线程局部(C++11 起)对象的零初始化。
而在enseignement中它说:
常量初始化是在静态和线程局部对象的零初始化之后以及所有其他初始化之前执行的。
正如您所看到的,cppref 使用“instead”,而第二个站点使用“after”。两者哪个是正确的?也就是说,零初始化是否总是首先发生,然后如果可能的话,如第二个站点所暗示的那样进行常量初始化,或者反之亦然。
那里给出的例子如下:
#include <iostream>
#include <array>
struct S {
static const int c;
};
const int d = 10 * S::c; // not a constant expression: S::c has no preceding
// initializer, this initialization happens after const
const int S::c = 5; // constant initialization, guaranteed to happen first
int main()
{
std::cout << "d = " << …
Run Code Online (Sandbox Code Playgroud) c++ initialization compile-time-constant constant-expression c++11