让我们说,给定C++ 17 if constexpr和Concepts TS(例如,在最近的gcc版本中),我们想检查模板函数中的类型是否具有嵌套类型:
#include <iostream>
struct Foo { using Bar = int; };
template<typename T>
void doSmth(T)
{
if constexpr (requires { typename T::Bar; })
std::cout << "has nested! " << typename T::Bar {} << std::endl;
else
std::cout << "no nested!" << std::endl;
}
int main()
{
doSmth(Foo {});
//doSmth(0);
}
Run Code Online (Sandbox Code Playgroud)
概念的文档很少,所以我可能错了,但似乎就是这样(并且实例是在Wandbox上).
现在让我们考虑一下取消注释另一个doSmth调用时会发生什么.似乎有理由期望require-clause将评估false,并且将采取意志的else分支if constexpr.与此相反,gcc使这成为一个很难的错误:
prog.cc: In instantiation of 'void doSmth(T) [with T = int]':
prog.cc:17:13: required from …Run Code Online (Sandbox Code Playgroud) 假设我们给出了一个模板实例化Container<U, Args...>(想想Container是一个std::vector)和一个非模板类型T,我们需要检查是否可以调用push_back一个类型的对象Container<T>.这是使用探测器成语的代码:
#include <iostream>
#include <vector>
#include <set>
#include <string>
#include <type_traits>
#include <boost/iterator.hpp>
#include <boost/range.hpp>
template<typename, typename>
struct replace
{
using type = struct Error;
};
template<template<typename...> class Container, typename U, typename T>
struct replace<Container<U>, T>
{
using type = Container<T>;
};
template<typename Container, typename T>
using replace_t = typename replace<Container, T>::type;
template<typename Placeholder, template<typename...> class Op, typename... Args>
struct isDetected : std::false_type {};
template<template<typename...> class Op, typename... Args> …Run Code Online (Sandbox Code Playgroud) 假设我们有一个这样的类,带有用户定义的演绎指南:
template<typename T, typename... Args>
struct Foo
{
Foo(Args&&...) { std::cout << "just Args: " << __PRETTY_FUNCTION__ << std::endl; }
Foo(Args&&..., T&&) { std::cout << "Args and T: " << __PRETTY_FUNCTION__ << std::endl; }
};
template<typename... Args>
Foo(Args&&...) -> Foo<Void, Args...>;
Run Code Online (Sandbox Code Playgroud)
现在让我们尝试创建这个类的实例:Foo foo { 10 };.什么是推导出的模板参数以及将调用哪个构造函数?
经过一些实验后,它取决于编译器.即,GCC 7和铛6(从主干)似乎选择自动引导,实例化T与int和Args用空包,因此输出是
Args and T: Foo<T, Args>::Foo(Args&& ..., T&&) [with T = int; Args = {}]
Run Code Online (Sandbox Code Playgroud)
另一方面,clang 5选择用户定义的指南:
just Args: Foo<Void, int>::Foo(Args &&...) [T = Void, …Run Code Online (Sandbox Code Playgroud) 我正在读取一个大文件(1-10 GB)并计算一些简单的统计数据,比如计算一个字符。在这种情况下流式传输是有意义的,所以我使用了 lazy ByteStrings。特别是,我的main样子
import qualified Data.ByteString.Lazy as BSL
main :: IO ()
main = do
contents <- BSL.readFile "path"
print $ computeStats contents
Run Code Online (Sandbox Code Playgroud)
computeStats在这种情况下,细节可能并不重要。
使用 运行它时+RTS -sstderr,我看到了这个:
MUT time 0.938s ( 1.303s elapsed)
Run Code Online (Sandbox Code Playgroud)
请注意 CPU 时间和已用时间之间的差异。除此之外,运行 under/usr/bin/time显示类似的结果:
0.89user 0.45system 0:01.35elapsed
Run Code Online (Sandbox Code Playgroud)
我正在测试的文件在 中tmpfs,因此实际磁盘性能不应该是一个因素。
system在这种情况下如何减少时间?我尝试明确设置文件句柄的缓冲区大小(对运行时间没有统计上的显着影响)以及mmaping 文件并将其包装成一个ByteString(运行时间实际上变得更糟)。还有什么值得尝试的?
假设我们有一些像这样的代码,哪些类型很好:
{-# LANGUAGE RankNTypes #-}
data Foo a
type A a = forall m. Monad m => Foo a -> m ()
type PA a = forall m. Monad m => Foo a -> m ()
type PPFA a = forall m. Monad m => Foo a -> m ()
_pfa :: PPFA a -> PA a
_pfa = _pfa
_pa :: PA a -> A a
_pa = _pa
_pp :: PPFA a -> A a
_pp x = …Run Code Online (Sandbox Code Playgroud) tl; dr:我正在尝试重写一些在 Haskell 中具有 sigma 类型列表的依赖类型代码,但我似乎无法为存在对象生成单例,换句话说,这段代码失败了:
data Foo :: Type where
Foo :: forall foo. Sing foo -> Foo
$(genSingletons [''Foo])
Run Code Online (Sandbox Code Playgroud)
更长的版本如下。
假设这个 Idris 代码作为模型:
data AddrType = Post | Email | Office
data AddrFields : AddrType -> Type where
PostFields : (city : String) -> (street : String) -> AddrFields Post
EmailFields : (email : String) -> AddrFields Email
OfficeFields : (floor : Int) -> (desk : Nat) -> AddrFields Office
Addr : Type
Addr = (t : AddrType …Run Code Online (Sandbox Code Playgroud) 我正在尝试对序列进行可组合折叠(类似于 foldl 库),但是在类型级别完成了更多的工作,希望编译器能够更轻松地进行内联和 CSE 处理(这些希望不是根据一些实验没有根据)。
为此,我有一个类型类(这是一个非常简化的示例):
class Statistic a where
type StateOf a = k | k -> a
type ResultOf a = k | k -> a
extract :: StateOf a -> ResultOf a
computeStep :: StateOf a -> Double -> StateOf a
...
Run Code Online (Sandbox Code Playgroud)
我也有几个基本实例
data Stats = Min | Max | Avg | Stddev
instance Statistic 'Min where ...
instance Statistic 'Max where ...
...
Run Code Online (Sandbox Code Playgroud)
以及一个组合实例
data a ::: b = a ::: b
instance (Statistic a, Statistic …Run Code Online (Sandbox Code Playgroud) 假设我们想要构建一个表示典型操作的类型,比如说,一个无锁算法:
newtype IntPtr = IntPtr { ptr :: Int } deriving (Eq, Ord, Show)
data Op r where
OpRead :: IntPtr -> Op Int
OpWrite :: IntPtr -> Int -> Op ()
OpCAS :: IntPtr -> Int -> Int -> Op Bool
Run Code Online (Sandbox Code Playgroud)
理想情况下,我们希望使用方便do注释在此模型中表示一些算法,例如(假设相应read = OpRead且cas = OpCAS出于美学原因)维基百科示例的以下几乎字面翻译:
import Prelude hiding (read)
import Control.Monad.Loops
add :: IntPtr -> Int -> Op Int
add p a = snd <$> do
iterateUntil fst $ do …Run Code Online (Sandbox Code Playgroud) 例如,我正在编写一个库函数,count_char(const char *str, int len, char ch)它检测正在运行的 CPU 支持的 SIMD 扩展并将调用分派到 AVX2 或 SSE4.2 优化版本。因为我想避免cpuid每次调用执行几个指令的惩罚,所以我试图在第一次调用函数时只执行一次(可能由不同的线程同时调用)。
在 C++ 领域,我只会做类似的事情
int count_char(const char *str, int len, char ch) {
static const auto fun_ptr = select_simd_function();
return (*fun_ptr)(str, len, ch);
}
Run Code Online (Sandbox Code Playgroud)
并依赖于 C++ 语义static来保证它只被调用一次而没有任何竞争条件。但是在纯 C 中做到这一点的最佳方法是什么?
这是我想出的:
pthread_once- 不确定它有什么开销,而且它可能会给 Windows 带来麻烦。fun_ptr为thread_local …假设我有一个可以取消装箱/重新装箱的值的类:
class Unboxable a (rep :: RuntimeRep) (unboxedTy :: TYPE rep) | a -> rep, a -> unboxedTy where
unbox :: a -> unboxedTy
rebox :: unboxedTy -> a
Run Code Online (Sandbox Code Playgroud)
像这样的例子非常好:
instance Unboxable Int 'IntRep Int# where
unbox (I# w) = w
rebox = I#
Run Code Online (Sandbox Code Playgroud)
但是如果我尝试支持不可装箱值的元组,例如
instance (Unboxable a repa unboxedTyA, Unboxable b repb unboxedTyB)
=> Unboxable (a, b) ('TupleRep '[ repa, repb ]) (# unboxedTyA, unboxedTyB #) where
unbox (a, b) = (# unbox a, unbox b #)
rebox (# …Run Code Online (Sandbox Code Playgroud) 我在一些代码库上尝试了 Coverity,我在一个类似于
struct Foo
{
std::string name;
};
Foo getFoo();
//...
const auto& name = getFoo().name;
useName(name);
Run Code Online (Sandbox Code Playgroud)
这个代码有效吗?
我的直觉是它确实是无效的。但是,在搜索证明时,我遇到了[class.temporary]/6.4,这似乎表明它实际上格式良好。然而,Coverity 发出警告,Coverity 肯定是由一些比我更能解释标准的聪明人写的。
发出的具体 Coverity 警告是
取消引用返回的或超出范围的堆栈指针将在其作用域之后或函数返回之后访问堆栈上的无效位置。
在whateverSurroundingFunction() 中:指向在范围外返回或使用的局部堆栈变量的指针(CWE-562)
在随后的使用中name。前面的警告是
out_of_scope:类型的临时变量
Foo超出范围
和一种MRE的是这个(荣誉给@ user4581301在评论)。
SO 有一堆关于临时绑定引用的问题,但我所看到的每个问题都有略微不同的上下文,因此这里又出现了另一个问题。
haskell ×6
c++ ×4
templates ×2
c ×1
c++-concepts ×1
c++11 ×1
c++17 ×1
c++20 ×1
coverity ×1
gadt ×1
idris ×1
io ×1
lifetime ×1
linux ×1
performance ×1
rank-n-types ×1
sfinae ×1