我想使用以下代码比较C printf和coutC ++ 的速度cout:
#include <iostream>
int main()
{
for (int i = 0; i < 150000; i++)
std::cout << "Hello!";
}
Run Code Online (Sandbox Code Playgroud)
和此代码为printf:
#include <cstdio>
int main()
{
for (int i = 0; i < 150000; i++)
std::printf("Hello!");
}
Run Code Online (Sandbox Code Playgroud)
我运行了两个程序很多次,这就是结果(使用g ++编译器):
cout:17.116 s
printf:9.153秒
因此printf比快两倍cout。我在Stack Overflow中搜索了此行为背后的原因,发现它printf比cout它在cout对象中具有功能时要快。但是我也了解到,它cout比较慢,因为它与标准C流同步。
因此,我接下来要做的是使用以下代码关闭所有iostream标准流及其对应的标准C流的同步:
#include <iostream>
int main()
{
std::ios_base::sync_with_stdio(false);
for (int i = 0; i …Run Code Online (Sandbox Code Playgroud) 考虑这个库头:
#include<vector>
#include<algorithm>
#include<iostream>
namespace Lib {
namespace detail {
using namespace std;
template<class T>
void sort_impl(istream &in,ostream &out) {
vector<T> v;
{
int n;
in >> n;
v.resize(n);
}
for(auto &i : v) cin >> i;
sort(v.begin(),v.end());
for(auto i : v) out << i << endl;
}
}
inline void sort_std() {
detail::sort_impl<int>(std::cin,std::cout);
}
}
Run Code Online (Sandbox Code Playgroud)
detail命名空间是否成功地将库的客户端(以及库的其余部分实现)与此示例中的using-directive隔离开来?我对于为什么"使用命名空间std"被认为是不良做法的讨论不感兴趣?即使某些论据甚至适用于"包含良好"的使用指令.
请注意,有两个关于相同情况但存在使用声明的问题:
这可以与它们中的任何一个组合,但编辑将是严重的.
在介绍概念和约束之前,有几种方法可以模拟此编译时检查。以“ order()”功能为例:(如何在LessThanComparable没有概念或约束的情况下实施是另一回事)
使用 static_assert
template <typename T, typename U>
void order(T& a, U& b)
{
static_assert(LessThanComparable<U,T>, "oh this is not epic");
if (b < a)
{
using std::swap;
swap(a, b);
}
}
Run Code Online (Sandbox Code Playgroud)
这种方法不适用于函数重载。
使用 typename = enable_if
template <typename T, typename U,
typename = std::enable_if_t<LessThanComparable<U,T>>>>
void order(T& a, U& b)
{
if (b < a)
{
using std::swap;
swap(a, b);
}
}
Run Code Online (Sandbox Code Playgroud)
如果过分“聪明”的家伙用手指定了第三个参数怎么办?
使用enable_if的函数原型:
template <typename T, typename U>
std::enable_if_t<LessThanComparable<U,T>>, void> order(T& a, U& b) …Run Code Online (Sandbox Code Playgroud)分配器要求的cppreference页没有说分配器必须是可继承的,即没有说分配器一定不能是最终的。
但是,在许多库中,分配器是私有继承的,以利用无状态分配器的空基类优化。例如:
template <typename T, typename A = std::allocator<T>>
class Dummy_vector :private A {
// ...
A get_alloc() const
{
return static_cast<A>(*this);
}
// ...
};
Run Code Online (Sandbox Code Playgroud)
如果A是最终的,则该实现会中断。
一个可以分配器是最终的?我错过了什么?还是应该为最终分配器包括特殊代码?
(注意:通过“最终分配器的特殊代码”,我的意思是这样的:
template <
typename T,
typename A = std::allocator<T>,
bool = std::is_final<A>
>
class Dummy_vector :private A {
// version for nonfinal allocators
// ...
A get_alloc() const
{
return static_cast<A>(*this);
}
// ...
};
template …Run Code Online (Sandbox Code Playgroud) 我们的应用程序由https://myserver.com/myapp提供服务(由虚拟应用程序中的 IIS 提供)
从https://myserver.com/myapp返回的 HTML为:
<html>
<!-- This file is served as a virtual application from https://myserver.com/myapp-->
<head>
<script src="/myapp/file.js"></script>
</head>
<body>
</body>
Run Code Online (Sandbox Code Playgroud)
要注册服务人员,我需要添加子文件夹,如下所示
// This does not work since the app is served from /myapp
navigator.serviceWorker.register("/sw.js") // Fail, will try loading https://myServer.com/sw.js
// This works (registration successful)
navigator.serviceWorker.register("/myapp/sw.js") // This will register the sw.
Run Code Online (Sandbox Code Playgroud)
当我尝试使用正在等待就绪事件的服务工作者时,出现问题:
// Inside of file.js
navigator.serviceWorker.ready.then(...) // Will not fire
Run Code Online (Sandbox Code Playgroud)
我猜发生的情况是,ready 事件没有触发,因为 serviceworker“认为”它是从名为“MyApp”的子文件夹安装的,但是当 file.js 运行并尝试使用 serviceworker 时,它看起来像文件.js 从 root 提供服务,因此超出了 serviceworker 的范围。
关于如何处理这个问题有什么想法吗?我尝试使用范围参数,但我认为这仅用于限制范围,而不是扩展范围。 …
标准容器传播const。也就是说,如果容器本身是const,则它们的元素自动为const。例如:
const std::vector vec{3, 1, 4, 1, 5, 9, 2, 6};
ranges::fill(vec, 314); // impossible
const std::list lst{2, 7, 1, 8, 2, 8, 1, 8};
ranges::fill(lst, 272); // impossible
Run Code Online (Sandbox Code Playgroud)
内置数组还传播const:
const int arr[] {1, 4, 1, 4, 2, 1, 3, 5};
ranges::fill(arr, 141); // impossible
Run Code Online (Sandbox Code Playgroud)
但是,我注意到std::span(大概)不会传播const。最小的可重现示例:
#include <algorithm>
#include <cassert>
#include <span>
namespace ranges = std::ranges;
int main()
{
int arr[] {1, 7, 3, 2, 0, 5, 0, 8};
const std::span spn{arr};
ranges::fill(spn, 173); // this compiles
assert(ranges::count(arr, …Run Code Online (Sandbox Code Playgroud) 注意:这个问题是关于显式实例化的,而不是显式专业化的。
请看下面的例子:
template <bool A, typename X>
void f (X &x) {} // 1
template <bool A>
void f (int &x) {} // 2
template void f<true> (int &x); // 3
Run Code Online (Sandbox Code Playgroud)
假设我的最初目标是仅显式实例化第二个功能模板,A = true因此我编写line // 3。但是直观上,第一个定义也可以用line显式实例化,// 3这有点麻烦,因为我无法用当前的语法实际转义它,因为bool A在我的情况下无法推断出它。从理论上讲,我什至都不介意两个函数模板最终都被显式实例化,但是最有趣的部分是实际的编译结果。
(在编译成功的所有情况下,仅实例化第二个功能模板。)
原案。用msvc和编译clang。无法使用以下命令进行编译gcc:
错误:“ void f(int&)”的模版模板特殊性“ f”
在第一个功能模板中替换bool A为bool A = truegcc即可对其进行编译。
替换X &x为X &&x(转发参考)会使clang无法使用以下命令进行编译:
错误:“ f”的显式实例化的部分排序不明确
这是最激烈的案例的演示。 …
c++ language-lawyer function-templates explicit-instantiation
我有这段代码可以在GCC 9.1中正常工作:
#include <type_traits>
template< typename T >
class A
{
protected:
T value;
public:
template< typename U,
typename...,
typename = std::enable_if_t< std::is_fundamental< U >::value > >
A& operator=(U v)
{
value = v;
return *this;
}
};
template< typename T >
class B : public A<T>
{
public:
using A<T>::operator=;
template< typename U,
typename...,
typename = std::enable_if_t< ! std::is_fundamental< U >::value > >
B& operator=(U v)
{
this->value = v;
return *this;
}
};
int main()
{
B<int> obj; …Run Code Online (Sandbox Code Playgroud) template <typename T>
void call(T) { //#1
std::cout << "1" << std::endl;
}
template <typename T, typename...Args>
void call(T, Args...) { //#2
std::cout << "2" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
当我这样调用函数时
call(10);
Run Code Online (Sandbox Code Playgroud)
GCC,Clang和MSVC都使用#1。
但是,标准中的部分排序规则指出:
如果对应于P i的参数声明是一个函数参数包,则将其声明符ID 的类型与A 的parameter-type-list中的每个其余参数类型进行比较。每个比较都推导出模板参数用于A中的后续位置。模板参数包由功能参数包扩展。在部分订购期间,如果A i最初是一个函数参数包:
(10.1)如果P不包含对应于A i的函数参数类型,则A i被忽略;
(10.2)否则,如果P i不是函数参数包,则模板参数推导失败。
当我们从#2推论出#1时(T, Args...以A表示,T以P表示),P不包含与对应的模板参数Args...。Args...被忽略,因此可以成功地从#2推导出#1。
然后,以TA和T, Args...P 从#1推论出#2的结果也成功T = T, Args... = {}。
因此,根据局部排序规则,在调用时call(10),编译器应给出模棱两可的错误,但实际上所有编译器都称为#1,这是为什么呢?
c++ templates language-lawyer overload-resolution variadic-templates
我正在尝试学习如何使用 SFINAE。出于练习目的,我试图制作一个std::ostream包装器以制作自定义格式化程序。
这是我的 SFINAE 和自定义输出类。
// Tester
template <class O>
struct is_ostreamable {
template <class T>
static auto check(T t) -> decltype(std::declval<std::ostream &>() << t, std::true_type());
template <class>
static auto check(...) -> std::false_type;
public:
static constexpr bool value{std::is_same_v<decltype(check<O>(0)), std::true_type>};
};
// Custom class
struct CustomOutput {
// Constructor etc...
CustomOutput(std::ostream &os = std::cout) : os{os} {}
std::ostream &os;
// Problematic template function
template <class O, class = std::enable_if_t<is_ostreamable<O>::value>>
CustomOutput &operator<<(O o) {
os << o;
return *this;
} …Run Code Online (Sandbox Code Playgroud) c++ ×9
c++11 ×2
sfinae ×2
templates ×2
allocator ×1
c++14 ×1
c++17 ×1
c++20 ×1
const ×1
enable-if ×1
final ×1
inheritance ×1
name-hiding ×1
namespaces ×1
std-span ×1