我目前正致力于基于模板元编程的浮点运算实现.表示编译时浮点值的模板如下:
template<bool S , std::int16_t E , std::uint64_t M>
struct number{};
Run Code Online (Sandbox Code Playgroud)
由于使用硬编码的尾数,指数等初始化这些值是一个麻烦且容易出错的过程,我编写了一个模板,用于将十进制值转换为浮点值:
template<std::int64_t INT , std::uint64_t DECS>
struct decimal{};
Run Code Online (Sandbox Code Playgroud)
其中第一个参数表示积分部分,第二个参数表示小数位数.我认为这是一种常见且众所周知的方式.
然而,这种模式会遇到一些问题(如何输入负数小于一的数字?),其中最令我讨厌的事实之一就是没有办法在逗号之后输入零数字,即数字之类的0.00032
.
我是C++ 11意识到的,我正在思考一个用户定义的文字+ decltype()
方法(即使有一个宏#define FLOAT(x) decltype(x_MY_LITERAL)
),但我不确定这种方法在所有情境中是否可行,我的意思是,如果文字+ decltype可在模板参数的上下文中进行评估.
即使这可行,我想知道是否有其他可能的方法来解决这个问题.那么,在编译时通过tmp进行浮点式初始化有哪些替代方案呢?
仅仅为了完整性,我将描述我已经实施的替代方案,它们如何工作,以及它的功能和优点.问题本身仍然是开放的,允许任何人添加更多的替代品.
首先,我将描述我使用过的功能,以确保每个人都能理解代码.
我的图书馆,Turbo Metaprogramming Library,基于三个原则:
仅键入模板参数:完全通用的混合类型参数,值参数和模板模板参数非常难(几乎不可能),因此此库仅使用类型参数.无论何时需要使用值或模板,库都提供包装器以通过装箱传递这些参数.
统一表达式评估:在编程语言中工作时的首要需求之一是评估表达式并获取其价值的方法.Turbo提供tml::eval
元函数,它接受任何类型的表达式并返回(计算)其值.
通过模板专业化定制的通用算法和元函数:每当我可以使用C++ 11模板别名来避免繁琐的typename ::type
构造.我的惯例是在嵌套命名空间上定义实现模板(真正完成工作的元函数)impl
,并在当前命名空间上定义结果的C++ 11模板别名.由于这些别名直接返回结果,因此它们无法在复杂表达式上进行求值(考虑元函数瞬时add<X,Y>
,其中X
和Y
是lambda的变量.如果add
是结果的别名,则不起作用,因为评估没有意义.如果我们需要表达式(元函数)而不是直接的结果,我的惯例是在func
嵌套命名空间上为元函数添加别名.
这里有些例子:
using bits = tml::util::sizeof_bits<int>; //bits is a size_t integral …
Run Code Online (Sandbox Code Playgroud) c++ floating-point templates template-meta-programming c++11
我需要在编译时检查一些整数素数(将布尔值作为模板参数).
我写的代码做得很好:
#include <type_traits>
namespace impl {
template <int n, long long i>
struct PrimeChecker {
typedef typename std::conditional<
(i * i > n),
std::true_type,
typename std::conditional<
n % i == 0,
std::false_type,
typename PrimeChecker<n, (i * i > n ) ? -1 : i + 1>::type
>::type
>::type type;
};
template <int n>
struct PrimeChecker<n, -1> {
typedef void type;
};
} // namespace impl
template<int n>
struct IsPrime {
typedef typename impl::PrimeChecker<n, 2>::type type;
};
template<>
struct IsPrime<1> …
Run Code Online (Sandbox Code Playgroud) 常见的编译器优化是将尾递归函数转换为循环,从而加快执行时间并减少内存(堆栈)消耗:
int go_to_zero( int n )
{
if( n == 0 )
return 0;
else
return go_to_zero( n - 1 );
}
Run Code Online (Sandbox Code Playgroud)
我的问题很简单:在模板元编程上执行尾递归算法是否有任何性能优势(即减少编译时间)?
这是一个例子:
template<typename... Ts>
struct list {};
template<typename LIST>
struct reverse;
template<typename HEAD , typename... TAIL>
struct reverse<list<HEAD,TAIL...>>
{
using result = concat<typename reverse<list<TAIL...>>::result,list<HEAD>>;
};
template<>
struct reverse<list<>>
{
using result = list<>;
};
Run Code Online (Sandbox Code Playgroud)
与:
template<typename INPUT , typename OUTPUT>
struct reverse_impl;
template<typename HEAD , typename... TAIL , tyename... Ts>
struct reverse_impl<list<HEAD,TAIL...>,list<Ts...>>
{
using result = typename …
Run Code Online (Sandbox Code Playgroud) std::result_of
在编译时计算调用表达式的返回类型.
正如参考文献所述,如果调用std::result_of
格式错误,则会导致编译错误.但是假设我们需要的是在获得结果类型之前检查调用是否格式正确.
有没有办法写一个特征来检查调用表达式是否格式正确?
就像是:
template<typename F , typename... ARGS>
struct is_valid_call : public impl::is_valid_call<F,typelist<ARGS...>>
{};
namespace impl
{
struct sfinae_result{};
template<typename F , typename ARGS , typename ENABLED = sfinae_result>
struct is_valid_call;
template<typename F , typename... ARGS>
struct is_valid_call<F,typelist<ARGS...>,
decltype( std::declval<F>()(std::declval<ARGS>()...) )
> :
public std::true_type
{};
template<typename F , typename... ARGS>
struct is_valid_call<F,typelist<ARGS...>,sfinae_result> :
public std::false_type
{};
}
Run Code Online (Sandbox Code Playgroud)
编辑:当然,发布的解决方案不起作用
正如标题所说,是否有编译器日志记录设置,它提供编译期间编译器达到的最大瞬时deph?
如果编译超出了最大模板deph(在C++ 11模式下哪个GCC的默认值为900),则编译失败.但我需要的是获得编译器在成功编译期间达到的最大模板即时深度.
有一种方法:
public static <T> void addandDisp(Collection<T> cs, T t)
以下列方式调用:
List<? extends Object> ls2 = new LinkedList<Number>();
addandDisp(ls2,new Object());
Run Code Online (Sandbox Code Playgroud)
这给出了编译时错误.另一方面,如果我们只有一个参数,则调用成功.这是为什么 ?
此外,这是成功的:
List<? super String> ls1 = new LinkedList<String>();
addandDisp(ls1,new String());
Run Code Online (Sandbox Code Playgroud)
虽然这不是:
List<? super String> ls1 = new LinkedList<Object>();
addandDisp(ls1,new Object());
Run Code Online (Sandbox Code Playgroud)
底层逻辑是什么?
到目前为止,我知道更改cmake使用的目标C++编译器的最佳方法是CXX
在调用cmake之前更改环境变量:
$ export CXX="clang++" && cmake --build
Run Code Online (Sandbox Code Playgroud)
Travis CI构建设置CXX
并CC
相应地设置构建.所以,如果你有这个.travis.yml
:
language: cpp
compiler:
- gcc
- clang
script:
- cmake --build
- ./bin/foo
Run Code Online (Sandbox Code Playgroud)
第一次cmake
应该使用GCC和后者的Clang不是?
相反,GCC构建编译得很好(它是cmake使用的默认编译器),但Clang版本也使用GCC:
0.01s $ echo $ CC $ CXX
clang clang ++
命令"echo $ CC $ CXX"退出0.0.02s $ $ CXX --version
clang version 3.4(tags/RELEASE_34/final)目标:x86_64-unknown-linux-gnu线程模型:posix运行:cmake -G"Unix Makefiles"-Wno-dev ../cmake
- C编译器标识是GNU
- CXX编译器标识是GNU
- 检查工作C编译器:/ usr/bin/gcc
- 检查用于工作的C编译器:/ usr/bin/gcc - 工作
- 检测C编译器ABI信息
- 检测C编译器ABI信息 - 完成
- …
我的问题很简单:有可能获得指向std::queue
容器适配器底层存储的指针吗?
我正在使用SFML进行渲染的一些模拟,我使用draw()
SFML渲染目标(sf::RenderTarget
)的方法来绘制整个数据.该方法具有类似C的接口,期望指向数据的指针,以及std::size_t
具有要绘制的元素数量的指针.
由于数据存储在队列中用于某些目的,如果有某种方法可以将指针指向存储库底层而不是将数据复制到向量,我将很高兴.
我知道默认情况下std::queue
调整容器std::deque
,但我不知道如何实现循环缓冲区以及它的数据是否连续(所以我可以直接提取指向数据的指针).
看看下面的答案,让我注意到我没有使用std::deque
它,因为它看起来很像队列,但是因为我真的需要快速排队.我当然可以用std::vector
.如果性能不是这里的重点,那么我会使用push_back()
和erase( begin() )
矢量.但我需要的是快速排队以及有效地将该队列的数据移动到渲染目标的方法.当然,如果平衡排队与绘制它的努力进入平局,我将使用std::vector
.
我正在观看C++ 11/14元编程演讲,其中描述了常见算法和tmp模式的一些有效替代方案.
大多数效率增益来自使用可变参数模板而不是递归遍历,并且在许多情况下,使用可变参数模板的方法是扩展通过索引技巧或其他std::integer_sequence
即时技巧生成的可变参数包.
由于效率来自实例化a std::integer_sequence
,特别是别名std::make_integer_sequence
不是一项昂贵的任务,我想确保C++ 1y标准库的当前最先进的实现是足够有效的,以使make_integer_sequence
即时不是一个复杂的,耗时的/内存消耗的任务.
究竟std::make_integer_sequence
是如何在C++ 1y-ready编译器中实际实现的?
请注意,我不是要问如何有效地实现它,而是编译器供应商如何实际决定实现它.
make_sequence
我所知道的唯一实现是简单的O(n)递归方法和聪明的O(logN)划分和征服.
I'm currently implementing a compile-time 3d raster though template metaprogramming.
After implementing the algebraic basics (2d/3d/4d vectors, 3x3/4x4 matrices arithmetic, aabb2d/3d for culling purposes, etc), I noted that integer arithmetic is not good enough for vector transformations. So I started to write a fixed-point implementation:
The library has a base header with declarations of common metafunctions that the algebraic types will implement (To provide an uniform interface). Here is the set of definitions used by the fixed-point implementation:
template<typename T> …
Run Code Online (Sandbox Code Playgroud) c++ ×9
c++11 ×7
templates ×2
biicode ×1
c++14 ×1
cmake ×1
collections ×1
compile-time ×1
containers ×1
fixed-point ×1
g++4.8 ×1
generics ×1
java ×1
performance ×1
recursion ×1
sfinae ×1
travis-ci ×1
type-traits ×1