从bug 80985开始考虑这个例子:
template <class Func>
void call(Func f)
{
f();
}
void func() noexcept { }
int main()
{
call(func);
}
Run Code Online (Sandbox Code Playgroud)
正如您所做的那样,在启用所有警告的情况下进行编译会产生:
$ g++ -std=c++14 -Wall foo.cxx
foo.cxx:2:6: warning: mangled name for ‘void call(Func) [with Func = void (*)() noexcept]’ will change in C++17 because the exception specification is part of a function type [-Wnoexcept-type]
void call(Func f)
^~~~
Run Code Online (Sandbox Code Playgroud)
我应该怎么做这个警告呢?修复是什么?
[class.dtor]/15读取,强调我的:
一旦为对象调用析构函数,该对象就不再存在 ; 如果为生命周期结束的对象调用析构函数,则行为未定义(3.8).
但是,据我所知,这是标准中对"现有"对象的唯一引用.这似乎与[basic.life]形成鲜明对比,后者更具体:
类型对象的生命周期在以下情况
T结束:
如果
T是具有非平凡析构函数(12.4)的类类型,则析构函数调用将启动,或者对象占用的存储器被重用或释放.
我们在这里有两个不同的措辞:"对象的生命周期结束"和"对象不再存在",前者只发生在一个非平凡的析构函数中,后者发生在任何析构函数中.差异的意义是什么?一个物体不再存在的含义是什么?
#include <iostream>
template<typename T>
struct identity
{
typedef T type;
};
template<typename T> void bar(T) { std::cout << "a" << std::endl; }
template<typename T> void bar(typename identity<T>::type) { std::cout << "b" << std::endl; }
int main ()
{
bar(5); // prints "a" because of template deduction rules
bar<int>(5); // prints "b" because of ...?
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
我预计bar<int>(5)至少会产生歧义.这里涉及到关于模板函数重载决策的疯狂规则?
我想写一个类型特征来检查某个类型是否有成员member.如果member是公开的,有很多方法可以做到这一点(例如void_t),其中最简洁的可能是Yakkcan_apply(最终可以调用std::is_detected):
struct C {
int member;
};
template <typename T>
using member_type = decltype(&T::member);
template <typename T>
using has_member = can_apply<member_type, T>;
static_assert(has_member<C>{}, "!"); // OK
Run Code Online (Sandbox Code Playgroud)
但如果该成员是私人的,那么这种特性就会失败,因为访问权限member是不正常的(我们不是朋友),并且由于访问原因而形成不良与由于这种事情导致的不良形式之间没有区别.存在的原因:
class D {
int member;
};
static_assert(has_member<D>{}, "!"); // error
Run Code Online (Sandbox Code Playgroud)
有没有办法在所有访问控制中编写这样的成员检查程序?
我无法理解为什么gcc-8.2.0和clang-7.0.0都拒绝以下代码(这里的实时代码):
#include <array>
int main() {
constexpr std::array<int,3> v{1,2,3};
constexpr auto b = v.begin(); // error: not a constexpr
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有错误
error: '(std::array<int, 3>::const_pointer)(& v.std::array<int,3>::_M_elems)'
is not a constant expression (constexpr auto b = v.begin();)
Run Code Online (Sandbox Code Playgroud)
根据en.cppreference.com,begin()声明了成员函数constexpr.这是编译器错误吗?
实际上,如果值类型为TriviallyCopyable,则std :: copy的实现应避免多次分配,并使用大容量复制功能,例如std :: memmove
但是,该页面还指出,不采用执行策略的重载将constexpr自C ++ 20开始。该标准是否会禁止这些运行时优化(因为std::memmove不是constexpr),或者是否有一种方法可以优化constexpr运行时的功能?
也许我累了,但我坚持这个简单的部分专业化,这不起作用,因为non-type template argument specializes a template parameter with dependent type 'T':
template <typename T, T N> struct X;
template <typename T> struct X <T, 0>;
Run Code Online (Sandbox Code Playgroud)
更换0的T(0),T{0}或(T)0没有帮助.那么这种专业化甚至可能吗?
我正在玩一个用C++重载lambdas的技巧.特别:
// For std::function
#include <functional>
// For std::string
#include <string>
// For std::cout
#include <iostream>
template <class... F>
struct overload : F... {
overload(F... f) : F(f)... {}
};
template <class... F>
auto make_overload(F... f) {
return overload<F...>(f...);
}
int main() {
std::function <int(int,int)> f = [](int x,int y) {
return x+y;
};
std::function <double(double,double)> g = [](double x,double y) {
return x+y;
};
std::function <std::string(std::string,std::string)> h = [](std::string x,std::string y) {
return x+y;
};
auto fgh = make_overload(f,g,h); …Run Code Online (Sandbox Code Playgroud) 摘自标准20.12 [function.objects]:
template <class T> reference_wrapper<T> ref(T&) noexcept;
template <class T> reference_wrapper<const T> cref(const T&) noexcept;
template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;
Run Code Online (Sandbox Code Playgroud)
我习惯于=delete在成员函数的上下文中看到.目的是禁止编译器提供的操作.例如,使类不可复制或不可移动.
然而,在这种情况下,意图似乎是意图的记录.这是正确的吗?是否有其他情况需要使用=delete非成员函数,优选或不可避免?
考虑以下:
struct A {
A(float ) { }
A(int ) { }
};
int main() {
A{1.1}; // error: ambiguous
}
Run Code Online (Sandbox Code Playgroud)
这无法编译时出现关于模糊重载的错误A::A.两位候选人都被认为是可行的,因为要求很简单:
第二,为了
F成为一个可行的函数,每个参数都应该存在一个隐式转换序列(13.3.3.1),它将该参数转换为相应的参数F.
虽然存在从隐式转换序列double到int,该A(int )过载不是实际可行的(在规范,非C++ -标准的意义上) -这将涉及一个收缩转换,因此是形成不良.
为什么在确定可行的候选人的过程中不考虑缩小转换?尽管只有一个候选人可行,但是有没有其他情况下过载被认为是模棱两可的?