无论如何,我是否可以判断函数参数在 C++ 11 中是否是编译时间常数?我想根据结果对函数体进行分支。例如,如下所示;
template <T>
size_t get_length(const T &t)
{
return t.size();
}
template <typename T, size_t N>
size_t get_length(const std::array<T, N> &t)
{
return N;
}
// Maybe some template
??? foo(size_t length)
{
...
// If length could be evaluated at compile time,
return std::array<int, length>{};
...
// Otherwise,
return std::vector<int>(length);
}
// ??? and auto should be std::array if bar is std::array, std::vector if bar is std::vector or etc.
auto x = foo(get_length(bar));
Run Code Online (Sandbox Code Playgroud)
我相信这需要两项任务;首先,它应该能够确定一个值是否在编译时可评估。其次,如果可能的话,将值转换为编译时间常数。
无论如何有人可以做到这一点吗?或者有什么理由这是不可能的吗?似乎有人说使用模板函数,但这迫使调用者输入编译时间常数,而不是我想要的。
存在库源可用的情况,并且它通常必须支持变量参数,但实际上这些参数通常是常量.
然后可以通过对常量参数的特殊处理来优化事物(例如,使用静态数组而不是堆分配),但为此必须首先确定某些事物是否是常量(或者可能定义一些宏,但它不太方便).
所以这是一个有效的实现.
更新:也在这里:http://codepad.org/ngP7Kt1V
更新:这是一个更符合预期用途的更新.if(N==0)如果N不是0 ,编译器将不会为分支生成任何代码.如果需要,我们可以切换到完全不同的数据结构.当然它不完美,但这就是我发布这个问题的原因.
#include <stdio.h>
struct chkconst {
struct Temp { Temp( int x ) {} };
static char chk2( void* ) { return 0; }
static int chk2( Temp ) { return 0; }
};
#define is_const_0(X) (sizeof(chkconst::chk2(X))<sizeof(int))
#define is_const_0i(X) (sizeof(chkconst::chk2(X))>sizeof(char))
#define is_const(X) is_const_0( (X)^((X)&0x7FFFFFFF) )
#define const_bit(X1,bit) (is_const_0i((X1)&(1<<bit))<<bit)
#define const_nibl(X1,bit) const_bit(X1,bit) | const_bit(X1,(bit+1)) | const_bit(X1,(bit+2)) | const_bit(X1,(bit+3))
#define const_byte(X1,bit) const_nibl(X1,bit) | const_nibl(X1,(bit+4))
#define const_word(X1,bit) const_byte(X1,bit) …Run Code Online (Sandbox Code Playgroud) 我目前正在学习Haskell,有一件事令我感到困惑:
当我构建一个复杂的表达式(其计算需要一些时间)并且该表达式是常量(意味着它只构建已知的硬编码值)时,不会在编译时计算表达式.
来自C/C++背景我习惯于这种优化.
在Haskell/GHC中不执行此类优化(默认情况下)的原因是什么?有什么好处,如果有的话?
data Tree a =
EmptyTree
| Node a (Tree a) (Tree a)
deriving (Show, Read, Eq)
elementToTree :: a -> Tree a
elementToTree x = Node x EmptyTree EmptyTree
treeInsert :: (Ord a) => a -> Tree a -> Tree a
treeInsert x EmptyTree = elementToTree x
treeInsert x (Node a left right)
| x == a = Node x left right
| x < a = Node a (treeInsert x left) right
| …Run Code Online (Sandbox Code Playgroud) optimization performance haskell compile-time-constant compile-time
有没有办法确保在编译时评估如下表达式?
myList :: [Int]
myList = sort [3,2,0,1]
Run Code Online (Sandbox Code Playgroud) #include<iostream>
using namespace std;
template<int N> class Prime
{ // generate N prime numbers at compile time
public:
unsigned int arr[N]{};
constexpr Prime() {
int k=0;
for(unsigned int i=2; k<N; i++) {
bool isPrime = true;
for(int j=0; j<k; j++) {
if(arr[j] > i/2) break;
if(i % arr[j] == 0) {
isPrime = false;
break;
}
}
if(isPrime) arr[k++] = i;
}
}
};
int main()
{
Prime<50000> prime; // if 50000->5000, ok
for(auto& a : prime.arr) cout << a …Run Code Online (Sandbox Code Playgroud) c++ templates compiler-errors compile-time-constant constexpr
我知道这是一个简单的问题,但我很困惑.我有一个相当典型的gcc警告,通常很容易修复:
warning: comparison between signed and unsigned integer expressions
每当我有一个带有最高有效位的十六进制常量时,如0x80000000L,编译器会将其解释为无符号.例如,使用-Wextra编译此代码将导致警告(gcc 4.4x,4.5x):
int main()
{
long test = 1;
long *p = &test;
if(*p != 0x80000000L) printf("test");
}
Run Code Online (Sandbox Code Playgroud)
我已经特别为常量加了后缀,为什么会发生这种情况呢?
我正在尝试实现泛型类.它应该有一个属性,该属性需要一个编译时常量,我想将其设置为参数类型的名称.像这样的东西:
namespace Example
{
public class MyGeneric<T>
{
[SomeAttribute(CompileTimeConstant)]
public int MyProperty { get; set; }
private const string CompileTimeConstant = typeof(T).Name; // error CS0133:
// The expression being assigned to `Example.MyGeneric<T>.CompileTimeConstant' must be constant
}
}
Run Code Online (Sandbox Code Playgroud)
但是因为typeof(T).Name在运行时进行评估,所以它不起作用.可能吗?
我做了一个constexpr字符串类型,我打电话给StaticString.我从这个网站得到了这个想法.
我有一些奇怪的问题,编译器将变量视为constexpr一行,然后不是constexpr下一行.
这是代码:
constexpr StaticString hello = "hello";
constexpr StaticString hello2 = hello + " ";
constexpr StaticString world = "world";
constexpr StaticString both = hello + " world";
constexpr StaticString both2 = hello2 + world;
//This works fine (world is constexpr?)
//constexpr StaticString both3 = "hello " + world;
//ERROR: "world" is not constexpr
int main(void)
{
static_assert(hello[4] == 'o' ,"ERROR");
static_assert(hello == "hello", "ERROR");
static_assert(both2 == "hello world", …Run Code Online (Sandbox Code Playgroud) 我想在编译时实现 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
c++ ×5
compile-time ×4
templates ×3
c++11 ×2
constexpr ×2
haskell ×2
c ×1
c# ×1
comparison ×1
gcc ×1
gcc-warning ×1
generics ×1
optimization ×1
performance ×1
raku ×1
rakudo ×1
reflection ×1