考虑下面粘贴的代码.我已经定义了一个非常简单的类,编译器为其生成一个隐式推理指南,因此可以在没有显式模板参数的情况下构造它.但是,模板参数推导不适用于从简单别名模板构造对象,该模板仅直接转发到目标类:
template< typename A, typename B >
struct Foo {
Foo( A const &a, B const &b )
: a_(a), b_(b)
{ }
A a_;
B b_;
};
template< typename A, typename B >
using Bar = Foo<A, B>;
auto foobar() {
Foo r{1, 2};
Bar s{3, 4};
// ../src/geo/vector_test_unit.cpp: In function 'auto foobar()':
// ../src/geo/vector_test_unit.cpp:16:6: error: missing template arguments before 's'
// Bar s{3, 4};
// ^
return 1;
}
Run Code Online (Sandbox Code Playgroud)
正如您从上面的代码注释中看到的那样,g ++给出了一个关于在没有模板参数的情况下使用别名模板的错误.我希望在这样的实例中转发模板参数推导.
所以,我的问题:这是通过表达模板参数演绎提案的当前措辞的明确设计吗?或者这是该功能的当前g ++实现中未完成的功能还是错误?对于提案的作者或C++ ISO委员会来说,这将是一个更大的问题,但如果其中任何一个人看到这一点:是否希望该功能的最终措辞包括启用别名模板,例如是否为他们生成了隐含指南?
我可以理解,因为别名模板可以有任何类型的模板参数,编译器可能并不总是能够成功推导出目标类模板参数,但在这种情况下,我希望编译器能够在它可以直接用于目标类. …
书写是否const auto& [a, b] = f();延长从返回的对象的终身保障f(),或者至少对象a和b必然?通过阅读提案,我没有看到任何明显的语言,以确保它确实存在,除非它只是被其他东西覆盖.但是,以下内容并未延长临时的生命周期,因此我不知道它将如何覆盖:
const auto& a = std::get<0>(f());
Run Code Online (Sandbox Code Playgroud)
在论文的顶部,似乎表明它已被覆盖
分解声明的cv-qualifiers和ref-qualifier应用于为初始化程序引入的引用,而不是单个成员别名
但是在实际标准的拟议措辞中,我看到的最接近的提法如下,但我不知道如何阅读它以获得我正在寻找的保证:
如果e是未分类的id-expression,命名从分解声明的identifier-list引入的左值或引用,则decltype(e)是分解声明规范中给出的引用类型
似乎gcc和clang都延长了返回对象的生命周期,直到基于wandbox实验的范围结束.一个实现我自己类型的所有铃声和口哨声的丑陋似乎延长了外部对象及其他数据成员的生命周期.
虽然几乎可以肯定作者的意图,但我想确切地知道这种语言可以保证这是安全的.
C++ 17将按值添加此对象的副本捕获,捕获规范为[*this].
这有用吗?它与捕获this有何不同?这不可能在C++ 14中实现[tmp = *this]吗?
用于解释为什么P0018R3使用[=, tmp = *this]而不是[tmp = *this]在他们的示例中的奖金.如果他们使用过[tmp = *this],那么C++ 14解决方案的所有列出的缺点都将被消除.
C++ 17引入了ContiguousIterator的概念http://en.cppreference.com/w/cpp/iterator.然而,似乎没有计划contiguous_iterator_tag(通过我们现在以同样的方式random_access_iterator_tag)报告std::iterator_traits<It>::iterator_category.
为什么contiguous_iterator_tag失踪?
是否有传统的协议来确定迭代器是否是连续的?还是编译时间测试?
在过去我提到过,对于容器,如果有一个.data()成员转换为指向::value类型的指针,并且有.size()成员可转换为指针差异,那么应该假设容器是连续的,但我不能提取迭代器的类似特征.
一种解决方案可能是data为连续迭代器提供一个函数.
当然,连续概念&(it[n]) == (&(*it)) + n在所有情况下都有效n,但在编译时无法检查.
编辑:我发现这个视频把它放在更广泛的C++概念上下文中.CppCon 2016:"在现代多核世界中构建和扩展迭代器层次结构",作者:Patrick Niedzielski.解决方案使用概念(Lite),但最后的想法是连续的迭代器应该实现一个pointer_from函数(与我的data(...)函数相同).
结论是概念将有助于形式化理论,但它们并不神奇,在某种意义上,某个人会在某个地方定义新的特别命名的函数而不是连续的迭代器.这个讨论概括了分段迭代器(带有相应的函数segment和local),不幸的是它没有说明跨步指针.
在编写一些针对C++ 17的代码时,我遇到了一个障碍,它决定了合并两个兼容的std :: unordered_maps的操作的异常安全性.根据目前的工作草案 §26.2.7,表91部分内容涉及以下条件a.merge( a2 ):
要求:
a.get_allocator() == a2.get_allocator().尝试提取每个元素
a2并a使用哈希函数和密钥相等谓词将其插入a.在具有唯一键的容器中,如果键中的元素a与元素的键相等a2,则不会从中提取该元素a2.后置条件:指针和对转移元素的
a2引用引用那些相同的元素但作为成员a.引用传递元素的迭代器和引用的所有迭代器a都将失效,但剩余元素的迭代器a2将保持有效.抛出:除非散列函数或键等式谓词抛出,否则无效.
值得注意的是,这些条件强烈地让人联想到普通关联容器(std :: map)的要求,如§26.2.6,表90所示a.merge( a2 ):
要求:
a.get_allocator() == a2.get_allocator().尝试提取每个元素
a2并a使用比较对象将其插入a.在具有唯一键的容器中,如果键中的元素a与元素的键相等a2,则不会从中提取该元素a2.后置条件:指针和对转移元素的
a2引用引用那些相同的元素但作为成员a.引用传递元素的迭代器将继续引用它们的元素,但它们现在表现为迭代器a,而不是a2.抛出:除非比较对象抛出,否则无效.
我需要合并两个std :: unordered_maps和相同数量的元素,我可以确保这两个元素在两个容器中都是唯一的,这意味着包含合并结果的地图将使之前拥有的元素数量增加一倍,并且容器合并 …
在cppref中,以下内容一直持续到C++ 17:
f(std::shared_ptr<int>(new int(42)), g())如果g在之后调用new int(42)并抛出异常,则可能导致内存泄漏的代码,同时f(std::make_shared<int>(42), g())是安全的,因为两个函数调用永远不会交错.
我想知道在C++ 17中引入了哪些更改使其不再适用.
假设我有一个类型的对象
std::map<std::string, std::tuple<int, float>> data;
Run Code Online (Sandbox Code Playgroud)
是否可以以嵌套的方式访问元素类型(例如,当在ranged for循环中使用时)
for (auto [str, [my_int, my_float]] : data) /* do something */
Run Code Online (Sandbox Code Playgroud) 请参阅以下返回可选项的示例UserName- 可移动/可复制类.
std::optional<UserName> CreateUser()
{
UserName u;
return {u}; // this one will cause a copy of UserName
return u; // this one moves UserName
}
int main()
{
auto d = CreateUser();
}
Run Code Online (Sandbox Code Playgroud)
为什么要return {u}复制和return u移动?
这是相关的coliru样本:http://coliru.stacked-crooked.com/a/6bf853750b38d110
另一个案例(感谢@Slava的评论):
std::unique_ptr<int> foo()
{
std::unique_ptr<int> p;
return {p}; // uses copy of unique_ptr and so it breaks...
}
Run Code Online (Sandbox Code Playgroud) 如下代码:
#include <type_traits>
struct X {
static constexpr void x() {}
};
template <class T1, class T2>
constexpr bool makeFalse() { return false; }
template <class T>
void foo() {
T tmp;
auto f = [](auto type) {
if constexpr (makeFalse<T, decltype(type)>()) {
T::x(); // <- clang does not discard
} else {
// noop
}
};
}
int main() {
foo<int>();
}
Run Code Online (Sandbox Code Playgroud)
不使用Clang编译,但是使用GCC编译。我看不到这段代码有什么问题,但是我不确定。Clang对吗?