我喜欢D的一些功能,但如果它们带来运行时惩罚会有兴趣吗?
为了比较,我实现了一个简单的程序,用C++和D计算许多短向量的标量积.结果令人惊讶:
C++真的几乎快了五倍,还是我在D程序中犯了错误?
我在一个温和的最近的Linux桌面上用g ++ -O3(gcc-snapshot 2011-02-19)和D和dmd -O(dmd 2.052)编译了C++.结果可在多次运行中重现,标准偏差可忽略不计.
这里的C++程序:
#include <iostream>
#include <random>
#include <chrono>
#include <string>
#include <vector>
#include <array>
typedef std::chrono::duration<long, std::ratio<1, 1000>> millisecs;
template <typename _T>
long time_since(std::chrono::time_point<_T>& time) {
long tm = std::chrono::duration_cast<millisecs>( std::chrono::system_clock::now() - time).count();
time = std::chrono::system_clock::now();
return tm;
}
const long N = 20000;
const int size = 10;
typedef int value_type;
typedef long long result_type;
typedef std::vector<value_type> vector_t;
typedef typename vector_t::size_type size_type;
inline value_type scalar_product(const vector_t& x, const vector_t& …
Run Code Online (Sandbox Code Playgroud) 任何只包含return语句的函数都可以声明
constexpr
,因此如果所有参数都是,constexpr
并且只constexpr
在其体内调用函数,则允许在编译时进行计算.有没有理由不宣布任何此类功能constexpr
?
例:
constexpr int sum(int x, int y) { return x + y; }
constexpr i = 10;
static_assert(sum(i, 13) == 23, "sum correct");
Run Code Online (Sandbox Code Playgroud)
任何人都可以提供一个例子来声明一个函数constexpr
会造成什么伤害吗?
一些初步想法:
即使没有充分的理由宣布一个函数,constexpr
我也无法想象该constexpr
关键字具有过渡角色:它在代码中的缺失不需要编译时评估将允许那些不实现编译时评估的编译器仍然编译该代码(但是在使用需要它们的代码上可靠地失败constexpr
).
但是我不明白:如果没有充分的理由不宣布函数constexpr
,为什么标准库中的每个函数都没有被声明constexpr
?(你不能说它还没有完成,因为还没有足够的时间去做,因为为所有人做这件事是明智的 - 与决定每一个功能是否成功相反constexpr
.) - - 我知道N2976
故意不要求cstrs用于许多标准库类型,例如容器,因为这对于可能的实现来说太有限了.让我们从参数中排除它们并且只是想知道:一旦标准库中的一个constexpr
类型实际上有一个cstr,为什么不是每个函数都在它上面声明constexpr
?
在大多数情况下,你也不能说你可能不想constexpr
仅仅因为你没有设想任何编译时使用而声明一个函数
:因为如果其他人退出.将使用您的代码,他们可能会看到您没有这样的用途.(当然,也可以用于类型特征类型和类似的东西.)
所以我想有一个很好的理由和一个故意不宣布功能的好例子constexpr
?
("每个函数"我总是指:满足存在要求的每个函数constexpr
,即被定义为单个return语句,只接受带有constexpr cstrs的类型的参数,并且只调用constexpr …
在C++ 0x中,可以创建一个constexpr std :: tuple,例如
#include <tuple>
constexpr int i = 10;
constexpr float f = 2.4f;
constexpr double d = -10.4;
constexpr std::tuple<int, float, double> tup(i, f, d);
Run Code Online (Sandbox Code Playgroud)
还可以在运行时查询std :: tuple,例如通过
int i2 = std::get<0>(tup);
Run Code Online (Sandbox Code Playgroud)
但是在编译时无法查询它,例如,
constexpr int i2 = std::get<0>(tup);
Run Code Online (Sandbox Code Playgroud)
将抛出编译错误(至少使用最新的g ++快照2011-02-19).
有没有其他方法在编译时查询constexpr std :: tuple?
如果没有,是否有一个概念上的原因,为什么不应该查询它?
(我知道避免使用std :: tuple,例如,通过使用boost :: mpl或boost :: fusion,但不知何故,如果不在新标准中使用元组类,这听起来是错误的......).
顺便问一下,有人知道为什么
constexpr std::tuple<int, float, double> tup(i, f, d);
Run Code Online (Sandbox Code Playgroud)
编译好,但是
constexpr std::tuple<int, float, double> tup(10, 2.4f, -10.4);
Run Code Online (Sandbox Code Playgroud)
不?
非常感谢提前! - 啦
如果没有声明constexpr
,std::forward
将丢弃constexpr-ness以用于转发参数的任何函数.为什么std::forward
不宣布constexpr
自己这样可以保留constexpr-ness?
示例:(使用g ++ snapshot-2011-02-19测试)
#include <utility>
template <typename T> constexpr int f(T x) { return -13;}
template <typename T> constexpr int g(T&& x) { return f(std::forward<T>(x));}
int main() {
constexpr int j = f(3.5f);
// next line does not compile:
// error: ‘constexpr int g(T&&) [with T = float]’ is not a constexpr function
constexpr int j2 = g(3.5f);
}
Run Code Online (Sandbox Code Playgroud)
注意:从技术上讲,很容易制作std::forward
constexpr,例如,如此(请注意,g std::forward
已被替换为fix::forward
):
#include <utility>
namespace fix …
Run Code Online (Sandbox Code Playgroud) 该boost::mpl
算法似乎不能够在工作std::tuple
类型的开箱即用的例如,下列不编译(升压1.46.0,G ++快照2011-02-19):
#include <tuple>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/contains.hpp>
namespace mpl=boost::mpl;
typedef mpl::vector<int,float,bool> types;
static_assert(mpl::contains<types, float>::value, "vector contains bool");
typedef std::tuple<int,float,bool> types2;
// the following does not compile:
// error: no class template named ‘apply’ in ‘struct boost::mpl::contains_impl<boost::mpl::non_sequence_tag>’
static_assert(mpl::contains<types2, float>::value, "tuple contains bool");
Run Code Online (Sandbox Code Playgroud)
使boost::mpl
算法工作的最简单方法是什么std::tuple
?
boost::fusion
提供此功能(因为它这样做boost::tuple
)?boost::tuple
以std::tuple
容易吗?在基类中调用非模板化成员函数时,可以将其名称导入using
到派生类中,然后使用它.这也适用于基类中的模板成员函数吗?
只是using
它不起作用(使用g ++ - snapshot-20110219 -std = c ++ 0x):
template <typename T>
struct A {
template <typename T2> void f() { }
};
template <typename T>
struct B : A<T> {
using A<T>::f;
template <typename T2> void g() {
// g++ throws an error for the following line: expected primary expression before `>`
f<T2>();
}
};
int main() {
B<float> b;
b.g<int>();
}
Run Code Online (Sandbox Code Playgroud)
我知道明确地为基类添加前缀
A<T>::template f<T2>();
Run Code Online (Sandbox Code Playgroud)
工作正常,但问题是:是否有可能没有和使用简单的使用声明(就像它f
不是模板函数的情况一样)?
万一这是不可能的,有谁知道为什么?