这是一个返回数组引用的转换函数:
struct S {
typedef int int_array_20[20];
operator int_array_20& ();
};
Run Code Online (Sandbox Code Playgroud)
没有可能做同样的事情typedef吗?我尝试过的:
struct S {
operator int (&()) [10];
};
Run Code Online (Sandbox Code Playgroud)
但克朗抱怨道:
error: C++ requires a type specifier for all declarations
operator int (&()) [10];
~ ^
error: conversion function cannot have any parameters
operator int (&()) [10];
^
error: must use a typedef to declare a conversion to 'int [10]'
error: conversion function cannot convert to an array type
Run Code Online (Sandbox Code Playgroud)
请问:
必须使用typedef来声明转换为'int [10]'
意味着typedef不可或缺?
编辑
如果typedef …
c++ typedef type-conversion conversion-operator language-lawyer
class B {
public:
virtual void f(){
printf("B\n");
}
};
class D : public B {
public:
void f() {
printf("D\n");
}
};
int main(void)
{
B* d = new D();
d->f();
auto b = *d;
b.f();
}
Run Code Online (Sandbox Code Playgroud)
因为d->f();,输出是D.这是正确的.但是b.f();,输出是B.这是正确的吗?
为什么std::array在这里以不同方式实例化数据类型
using T = const int *;
std::array<T, 4> x = { &a, &b, &c, &d }; // name: class std::array<int const *,4>
x[0] = &c; // OK : non-constant pointer
*x[0] = c; // Error : constant data
Run Code Online (Sandbox Code Playgroud)
相比这里?
using T = int *;
std::array<const T, 4> x = { &a, &b, &c, &d }; // name: class std::array<int * const,4>
x[0] = &c; // Error : constant pointer
*x[0] = c; // OK : non-constant data …Run Code Online (Sandbox Code Playgroud) 关于从函数返回并绑定到rvalue/const左值引用的对象的生命周期的延长,我有一些不清楚的信息.来自这里的信息.
不会扩展对return语句中函数的返回值的临时绑定:它会在返回表达式的末尾立即销毁.这样的函数总是返回一个悬空引用.
如果我理解正确,引用声称返回语句返回的对象的生命周期是不可扩展的.但最后一句话表明,它只适用于返回引用的函数.
在海湾合作委员会,从下面的代码我得到以下输出:
struct Test
{
Test() { std::cout << "creation\n"; }
~Test() { std::cout << "destruction\n"; }
};
Test f()
{
return Test{};
}
int main()
{
std::cout << "before f call\n";
Test && t = f();
std::cout << "after f call\n";
}
Run Code Online (Sandbox Code Playgroud)
before f call
creation
after f call
destruction
Run Code Online (Sandbox Code Playgroud)
所以看起来生命延长了.
是否应延长与此类参考相关的临时对象的生命周期?您还可以提供更明确的信息来源吗?
template<class Key1, class Key2, class Type> class DualMultimapCache
{
public:
std::list<std::reference_wrapper<Type>> get(Key1 const & key);
std::list<std::reference_wrapper<Type>> get(Key2 const & key);
template<class ...Args> Type & put(Key1 const & key, Args const & ...args);
template<class ...Args> Type & put(Key2 const & key, Args const & ...args);
};
Run Code Online (Sandbox Code Playgroud)
在这里,我有一个类的公共接口.基础数据结构无关紧要.一切都将只是正常工作时Key1,并Key2有不同的类型.如果它们最终成为相同的类型,则过载可能是不可能的.我这是对的吗?
如果我是,有没有办法分离过载,同时保持签名尽可能干净?
编辑:这是一个更深入的样本
template<class Key1, class Key2, class Type> class DualMultimapCache
{
public:
std::list<std::reference_wrapper<Type>> get(Key1 const & key);
std::list<std::reference_wrapper<Type>> get(Key2 const & key);
template<class ...Args> Type & put(Key1 const & key, …Run Code Online (Sandbox Code Playgroud) c++ templates overloading overload-resolution class-template
感谢valgrind中的一些分段错误和警告,我发现这段代码不正确,并且在for-range循环中有一些悬空引用.
#include<numeric>
#include<vector>
auto f(){
std::vector<std::vector<double>> v(10, std::vector<double>(3));
iota(v[5].begin(), v[5].end(), 0);
return v;
}
int main(){
for(auto e : f()[5])
std::cout << e << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它看起来好像begin并end从临时取出,并循环丢失.
当然,一种方法是做
auto r = f()[5];
for(auto e : r)
std::cout << e << std::endl;
Run Code Online (Sandbox Code Playgroud)
但是,我想知道为什么for(auto e : f()[5])是一个错误,如果有更好的方法或某种方式设计f或甚至容器(std::vector)以避免这个陷阱.
随着迭代循环是比较明显的,为什么这个问题发生(begin和end来自不同的临时对象)
for(auto it = f()[5].begin(); it != f()[5].end(); ++it)
Run Code Online (Sandbox Code Playgroud)
但是在for-range循环中,就像在第一个例子中一样,这个错误似乎很容易.
最近有一个恭维问题,由此片段说明:
struct Base
{
};
template<typename T>
struct A : Base
{
A(){}
A(Base&&) {}
};
A<int> foo()
{
A<double> v;
return v;
}
int main()
{
auto d = foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Gcc说没关系,但是clang不同意并说"候选构造函数不可行:第一个参数A(Base &&){}"没有已知的从'A'到'Base &&'的转换,请亲自看看:https://godbolt.org/Z/Y7mwnU
任何一种读者是否能够帮助支持任何一种观点?
我遇到了一个奇怪的案例。
// this does not work, and reports:
// constexpr variable 'b' must be initialized by a constant expression
int main() {
const double a = 1.0;
constexpr double b = a;
std::cout << b << std::endl;
}
// this works...
int main() {
const int a = 1;
constexpr int b = a;
std::cout << b << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
有什么特别之处double所以它不能constexpr工作?
它是错误还是标准允许?
#include <iostream>
#include <map>
#include <unordered_map>
int main() {
std::unordered_map<int,int> mm {{44,44}, {33.3, 54}, {222.2,222.2}};
for(auto& [f,s] :mm) {
std::cout<<f<<" - "<<s<<std::endl;
}
std::map<int,int> m {{44,44}, {33.3, 54}, {222.2,222.2}};
for(auto& [f,s] :m) {
std::cout<<f<<" - "<<s<<std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
在wandbox.org 上使用 clang10 和 gcc10对其进行测试。std::set和没有这样的问题std::unordered_set。
当使用不同的右值引用类型调用重载函数时,我在代码中遇到了意外行为。下面的代码片段演示了这个问题:
#include <iostream>
void foo(int&& x)
{
std::cout << "int Rvalue: " << x << std::endl;
}
void foo(float&& x)
{
std::cout << "float Rvalue: " << x << std::endl;
}
int main()
{
int int_x = 1;
float float_x = 5.14f;
foo(int_x);
foo(float_x);
}
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)float Rvalue: 1 int Rvalue: 5
我没有得到预期的输出(应该是“int Rvalue:1”和“float Rvalue:5”),而是观察到相反的顺序。我发现这种行为令人困惑,并且希望了解为什么会发生这种情况。
我确保理解右值引用的概念以及基于它们的重载如何工作。我也尝试过搜索类似的问题,但没有找到任何直接解决此特定情况的问题。
任何指导或解释将不胜感激。预先感谢您的帮助!