我想写一些带字符串文字的函数 - 只有一个字符串文字:
template <size_t N>
void foo(const char (&str)[N]);
Run Code Online (Sandbox Code Playgroud)
不幸的是,这太过于扩展并且会匹配任何数组char- 无论它是否是真正的字符串文字.虽然在编译时无法区分它们之间的区别 - 而不必在运行时求助调用者包装文字/数组 - 但这两个数组将在内存中完全不同的位置:
foo("Hello"); // at 0x400f81
const char msg[] = {'1', '2', '3'};
foo(msg); // at 0x7fff3552767f
Run Code Online (Sandbox Code Playgroud)
有没有办法知道字符串数据在内存中的位置,以便我至少可以assert使该函数仅采用字符串文字?(使用gcc 4.7.3,但实际上任何编译器的解决方案都会很棒).
考虑以下:
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++ -标准的意义上) -这将涉及一个收缩转换,因此是形成不良.
为什么在确定可行的候选人的过程中不考虑缩小转换?尽管只有一个候选人可行,但是有没有其他情况下过载被认为是模棱两可的?
以下代码:
variant<string> x = "abc";
cout << get<string>(x) << "\n";
Run Code Online (Sandbox Code Playgroud)
在g ++(版本7.2)下正常工作.但是,当使用libstdc ++在clang ++(版本5.0)下编译时,我在get方法中得到以下错误:
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../include/c++/7.2.0/variant:238:46: fatal error: cannot cast 'std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >' to its private base class 'std::__detail::__variant::_Variant_storage<false, std::
__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >'
return __get(std::in_place_index<_Np>, std::forward<_Variant>(__v)._M_u);
Run Code Online (Sandbox Code Playgroud)
这是编译器错误,还是我的代码以任何方式违法?
考虑这个问题,这是关于以下不编译的代码:
std::vector<int> a, b;
std::cout << (std::ref(a) < std::ref(b));
Run Code Online (Sandbox Code Playgroud)
它不会编译,因为向量比较运算的vector都是非成员函数模板,隐式转换是不允许考虑.但是,如果运算符被写为非成员非模板,则friend函数:
template <class T, class Allocator = std::allocator<T>>
class vector {
// ...
friend bool operator<(const vector& lhs, const vector& rhs) {
// impl details
}
};
Run Code Online (Sandbox Code Playgroud)
那么这个版本operator<将由ADL找到并被选为最佳可行的重载,并且原始示例将被编译.鉴于此,是否有理由选择我们目前拥有的非成员函数模板,还是应该将其视为标准中的缺陷?
给出两个非常简单的类:
class X
{
};
class Y : public X
{
};
Run Code Online (Sandbox Code Playgroud)
为什么说,随着锵和GCC针对C++ 14,std::is_assignable<X*, Y*>::value是false?true当我面向C++ 11时,我的设置就是Clang.
我不明白为什么这不起作用.知道模板和可变参数表达式折叠的人能解释发生了什么并提供一个有效的解决方案吗?
#include <iostream>
#include <string>
template <typename... Args>
void print(Args... args)
{
std::string sep = " ";
std::string end = "\n";
(std::cout << ... << sep << args) << end;
}
int main()
{
print(1, 2, 3);
}
Run Code Online (Sandbox Code Playgroud)
它应该打印出每个args,其间有一个空格,最后一个换行符.如果你删除了它,sep <<但是在打印时每个参数之间没有空格.
Clang接受以下代码,但gcc 拒绝它。
void h() { }
constexpr int f() {
return 1;
h();
}
int main() {
constexpr int i = f();
}
Run Code Online (Sandbox Code Playgroud)
这是错误消息:
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'constexpr int f()':
main.cpp:5:6: error: call to non-'constexpr' function 'void h()'
h();
~^~
main.cpp: In function 'int main()':
main.cpp:9:24: error: 'constexpr int f()' called in a constant expression
constexpr int i = f();
~^~
main.cpp:9:19: warning: unused variable 'i' [-Wunused-variable]
constexpr int i …Run Code Online (Sandbox Code Playgroud) 我目前正在使用Boost.Python为Python编写C++扩展.此扩展中的函数可能会生成一个包含错误信息的异常(除了描述发生的事件的人类可读字符串之外).我希望我可以将这个异常导出到Python,这样我就能抓住它并用额外的信息做些什么.
例如:
import my_cpp_module
try:
my_cpp_module.my_cpp_function()
except my_cpp_module.MyCPPException, e:
print e.my_extra_data
Run Code Online (Sandbox Code Playgroud)
不幸的是,Boost.Python似乎将所有C++异常(都是其子类std::exception)转换为RuntimeError.我意识到Boost.Python允许一个人实现自定义异常转换,但是,需要使用PyErr_SetObject一个PyObject*(对于异常的类型)和一个PyObject*(对于异常的值) - 我都不知道如何从我的Boost中获取. Python类.也许有一种方法(这将是伟大的),我还没有找到.否则有人知道如何导出自定义C++异常,以便我可以在Python中捕获它吗?
我试图迭代一些std::lists,对它们进行排序.这是天真的方法:
#include<list>
using namespace std;
int main(void){
list<int> a,b,c;
for(auto& l:{a,b,c}) l.sort();
}
Run Code Online (Sandbox Code Playgroud)
生产
aa.cpp:5:25: error: no matching member function for call to 'sort'
for(auto& l:{a,b,c}) l.sort();
~~^~~~
/usr/bin/../lib64/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_list.h:1586:7: note:
candidate function not viable: 'this' argument has type 'const
std::list<int, std::allocator<int> >', but method is not marked const
sort();
^
/usr/bin/../lib64/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_list.h:1596:9: note:
candidate function template not viable: requires 1 argument, but 0 were
provided
sort(_StrictWeakOrdering);
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
我是否正确地猜测大括号初始化程序正在创建这些列表的副本?有没有办法不复制它们,并使它们在循环中可修改?(除了制作指向它们的指针列表,这是我目前的解决方法).
在Herb Sutter中When Is a Container Not a Container?,他展示了一个将指针放入容器的示例:
// Example 1: Is this code valid? safe? good?
//
vector<char> v;
// ...
char* p = &v[0];
// ... do something with *p ...
Run Code Online (Sandbox Code Playgroud)
然后跟着它"改进":
// Example 1(b): An improvement
// (when it's possible)
//
vector<char> v;
// ...
vector<char>::iterator i = v.begin();
// ... do something with *i ...
Run Code Online (Sandbox Code Playgroud)
但实际上并没有提供令人信服的论据:
一般来说,当你想指向一个容器内的对象时,更喜欢使用迭代器而不是指针并不是一个糟糕的指导.毕竟,迭代器在与指针大致相同的时间和相同的方式上无效,并且迭代器存在的一个原因是提供一种"指向"包含对象的方法.因此,如果您有选择,请更喜欢将迭代器用于容器中.
不幸的是,你不能总是得到与迭代器相同的效果,你可以使用指针到容器.迭代器方法有两个主要的潜在缺点,当适用时我们必须继续使用指针:
您不能总是方便地使用可以使用指针的迭代器.(见下面的例子.)
在迭代器是一个对象而不仅仅是一个光头指针的情况下,使用迭代器可能会产生额外的空间和性能开销.
在向量的情况下,迭代器只是一个RandomAccessIterator.对于所有意图和目的,这是指针上的薄包装.一种实现甚至承认这一点:
// This iterator adapter is 'normal' in the sense that it does not …Run Code Online (Sandbox Code Playgroud)