我有以下代码:
#include <iostream>
#include <vector>
namespace X {
std::ostream& operator<<(std::ostream& os,const std::vector<double>& v){
for (int i=0;i<v.size();i++){os << v[i] << " ";}
return os;
}
namespace Y {
struct A {std::vector<double> x;};
std::ostream& operator<<(std::ostream& os,const A& a){
os << a.x << std::endl;
return os;
}
}
}
using namespace X;
int main(int argc, char** argv) {
std::vector<double> v(10,0);
std::cout << v << std::endl;
Y::A a;
std::cout << a << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
第一个重载是有效的,但第二个没有.由于某种原因,它找不到第一个.我收到错误:
no match for 'operator<<' (operand types are …
Run Code Online (Sandbox Code Playgroud) 假设有一个具有默认值的函数:
int foo(int x=42);
Run Code Online (Sandbox Code Playgroud)
如果这是由其他人这样调用:
int bar(int x=42) { return foo(x); }
int moo(int x=42) { return bar(x); }
Run Code Online (Sandbox Code Playgroud)
这当然只是一个人为的例子.但是,我有时情况非常相似.该参数仅从最高级别(moo
)传递到最低级别,并且仅在实际使用时才传递.关于这一点的坏处是,当我更改foo
为具有不同于42
我必须搜索所有调用者的默认值并相应地更改默认值时.
是否有一些模式/成语可以避免这种情况?
我想到的唯一简单的解决方案是
int bar() { return foo(); }
int bar(int x) { return foo(x); }
Run Code Online (Sandbox Code Playgroud)
但是,由于我有点懒,而且在实际代码中这会导致相当多的代码重复,我想避免这种情况.
问题
请耐心等待,这只是一个例子:
#include <algorithm>
#include <iterator>
struct foo {
static int my_transform(int x) { return x;}
static std::vector<int> my_transform(std::vector<int> x){
std::vector<int> result;
std::transform(x.begin(),x.end(),std::back_inserter(result),my_transform);
return result;
}
};
Run Code Online (Sandbox Code Playgroud)
我期待发生什么
有两个可能的重载my_transform
,但只有一个导致格式良好的模板实例化,而另一个模板实例化是不正确的.我希望丢弃不正确的一个以及上面的编译.
真正发生了什么
main.cpp:165:75: error: no matching function for call to
‘transform(std::vector<int>::iterator, std::vector<int>::iterator,
std::back_insert_iterator<std::vector<int> >, <unresolved overloaded function type>)’
std::transform(x.begin(),x.end(),std::back_inserter(result),my_transform);
^
Run Code Online (Sandbox Code Playgroud)
如何解决它
将函数指针转换为正确的类型可以解决歧义并编译:
static std::vector<int> foo::my_transform(std::vector<int> x){
std::vector<int> result;
typedef int (*my_transform_t)(int);
std::transform(x.begin(),
x.end(),
std::back_inserter(result),
static_cast<my_transform_t>(my_transform));
return result;
}
Run Code Online (Sandbox Code Playgroud)
问题
究竟是什么阻止了编译器选择"正确"的重载?考虑到只有一个可以导致有效的模板实例化,实际上并不存在歧义.
PS:请注意,这是C++ 98.在C++ 11及更高版本中,使用lambdas可以很容易地避免这个问题(感谢@appleapple指出这一点).
c++ templates function-pointers language-lawyer stl-algorithm
我很快为这个问题编写了下面的课程.
我正在寻找一种方式来合并addFruit()
与removeFruit()
减少的代码.
它们都使用相同的条件,但最后只是使用不同的函数调用.
我的代码:
#include <iostream>
#include <string>
#include <vector>
class MyClass
{
public:
void addFruit(const std::string &str, int count)
{
if (str == "apples")
addToVec(apples, count);
else if (str == "oranges")
addToVec(oranges, count);
else if (str == "lemons")
addToVec(lemons, count);
else if (str == "melons")
addToVec(melons, count);
else if (str == "bananas")
addToVec(bananas, count);
else
std::cout << "Unknown Fruit : " << str << '\n';
}
void removeFruit(const std::string &str)
{
if (str == "apples") …
Run Code Online (Sandbox Code Playgroud) 根据[dcl.fct]/2,下面的代码段是合法的.GCC和clang编译并执行代码,
#include <iostream>
int i = -1;
auto f()->auto&& { return i; }
int main(){
f() = 2;
std::cout << i << '\n';
}
Run Code Online (Sandbox Code Playgroud)
印花
2
Run Code Online (Sandbox Code Playgroud)
但是在C++中允许这个的目的是什么?
在上面的示例中,只需将trailing-return-type替换为,就可以获得相同的结果int&
.换句话说,我正在寻找一个示例,其中包含占位符类型的trailing-return-type将是有意义的.
C.45:不要定义仅初始化数据成员的默认构造函数;改用类内成员初始化器
给出的理由是
原因
使用类内成员初始化器可使编译器为您生成函数。编译器生成的函数可以更有效。
请注意,这是专门针对默认构造函数的,该默认构造函数除了初始化成员外不执行任何操作,并且该准则建议不要编写这样的构造函数。
“坏”的例子是:
Run Code Online (Sandbox Code Playgroud)Example, bad class X1 { // BAD: doesn't use member initializers string s; int i; public: X1() :s{"default"}, i{1} { } // ... };
在该特定示例(或任何其他示例)中,编译器生成的构造函数比用户提供的构造函数更有效率吗?
我天真地希望初始化程序列表提供与类初始化程序相同的优化机会。
代码说出了上千个单词,所以...
这是使a发生突变的未定义行为const int
:
struct foo {
int x;
void modify() { x = 3; }
};
void test_foo(const foo& f) {
const_cast<foo&>(f).modify();
}
int main(){
const foo f{2};
test_foo(f);
}
Run Code Online (Sandbox Code Playgroud)
那这个呢:
struct bar {
void no_modify() { }
};
void test_bar(const bar& b) {
const_cast<bar&>(b).no_modify();
}
int main(){
const bar b;
test_bar(b);
}
Run Code Online (Sandbox Code Playgroud)
const_cast
当方法不改变对象时,是否可以通过const对象调用非const方法?
PS:我知道no_modify
应该将其声明为const
,然后这个问题毫无意义,但假设bar
s的定义不能更改。
PPS:只需确保:不要在家中(或其他任何地方)这样做。我绝不会让这样的代码通过审查。可以轻松避免强制转换。这是一个语言律师问题。
我在玩 www.godbolt.org 来检查哪些代码会生成更好的汇编代码,但我不明白为什么这两种不同的方法会生成不同的结果(在汇编命令中)。
第一种方法是声明一个字符串,然后再设置一个值:
#include <string>
int foo() {
std::string a;
a = "abcdef";
return a.size();
}
Run Code Online (Sandbox Code Playgroud)
其中,在我的 gcc 7.4 ( -O3
) 输出中:
.LC0:
.string "abcdef"
foo():
push rbp
mov r8d, 6
mov ecx, OFFSET FLAT:.LC0
xor edx, edx
push rbx
xor esi, esi
sub rsp, 40
lea rbx, [rsp+16]
mov rdi, rsp
mov BYTE PTR [rsp+16], 0
mov QWORD PTR [rsp], rbx
mov QWORD PTR [rsp+8], 0
call std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace(unsigned long, unsigned long, char const*, unsigned …
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用初始化程序列表初始化动态声明的数组,但我注意到我必须使用 GCC 提供数组大小,否则会出现错误。如果忽略数组大小,使用 MSVC 尝试相同的操作不会导致任何错误。使用带有动态数组的初始值设定项列表时是否必须提供数组大小?这是实现定义的,这就是为什么两个编译器都不同的原因?
int *array { new int [3] {0, 1, 2} }; // Works with both MSVC and GCC.
int *array { new int [] {0, 1, 2} }; // Works only with MSVC, not GCC.
Run Code Online (Sandbox Code Playgroud) 我正在寻找一种使用 SFINAE 来实现某些功能的方法,该功能必须仅适用于某些容器:向量、列表、数组(设置在下面仅作为测试)
基于这个答案,我尝试了下面的代码,该代码使用了一个仅对所需容器返回 true 的特性类。
正如您在此处在线看到的,它失败了std::array
。
template <typename Container>
struct is_container : std::false_type { };
template <typename... Ts> struct is_container<std::array<Ts... >> : std::true_type { };
template <typename... Ts> struct is_container<std::vector<Ts...>> : std::true_type { };
template <typename... Ts> struct is_container<std::set<Ts... >> : std::true_type { };
template <typename... Ts> struct is_container<std::list<Ts... >> : std::true_type { };
template <typename... Ts> struct Dummy{};
int main()
{
std::cout << "Dummy: " << is_container<Dummy<int>>::value << '\n';
std::cout << "array: …
Run Code Online (Sandbox Code Playgroud) c++ ×10
templates ×2
const ×1
const-cast ×1
gcc ×1
optimization ×1
ostream ×1
sfinae ×1
stdarray ×1
visual-c++ ×1