是否可以编写仅用于类类型的部分模板特化,例如,从特定类继承或遵守可通过类型特征表达的其他约束?即,像这样:
class A{}
class B : public A{}
template<typename T>
class X{
int foo(){ return 4; }
};
//Insert some magic that allows this partial specialization
//only for classes which are a subtype of A
template<typename T>
class X<T>{
int foo(){ return 5; }
};
int main(){
X<int> x;
x.foo(); //Returns 4
X<A> y;
y.foo(); //Returns 5
X<B> z;
z.foo(); //Returns 5
X<A*> x2;
x2.foo(); //Returns 4
}
Run Code Online (Sandbox Code Playgroud) 我偶然发现了segvcatch库,它承诺将segfaults和浮点错误包装到适当的异常中.
使用这个库是安全的,如果我添加了捕获的所有段错误只会是空指针访问的前提条件(即,没有数组溢出或无效指针可能在segfaulting之前完全搞砸了内存,导致未定义的行为无论如何)?在捕获nullptr段错误后,程序是否仍然定义了语义?浮点错误呢?他们表现得更好/不同吗?
旁注:请不要评论说任何产生段错误的程序都是格式错误的,应该进行调试/修复.我知道,我同意.不过,我对这个问题很感兴趣.
在按值传递C/C++中的结构时,必须复制结构内容.编译器如何实现这一目标?即,通常为此副本发出哪些汇编指令?
这些时间有多快,例如与memcpy的调用相比?
现在考虑这段代码:
struct X { int i, j, k; };
void foo(X x);
void foo( int i, int j, int k);
Run Code Online (Sandbox Code Playgroud)
调用foo(X)和foo(int,int,int)之间有什么区别,或者生成的汇编代码是否相同(考虑参数的传递)?
通常,STL是为了速度而构建的.但是,在map和set数据结构上只有upper_bound和lower_bound,并且没有操作来检索具有小于输入键的最大键的条目k.为什么是这样?我知道我可以简单地做一个lower_bound并做一个--it来检索这个,但是根据数据结构,可以更有效地立即搜索正确的条目,而不是搜索另一个然后返回一步.
例如,std::map使用红黑树,即二叉搜索树.如果返回的upper_bound元素是大于根的最小元素,则--it必须返回到根,查询O(log n)附加成本.
如果这是Java,我会对设计决定没问题.但是,STL是为最大速度而构建的,那么为什么这个操作被遗漏了呢?
澄清:我不是在谈论std::upper_bound它可以采取另一种比较,但方法std::map和std::set.
请考虑以下代码:
template<typename T, size_t... i>
class Bar{};
template<typename T1, typename T2>
class Foo{};
template<typename T1, size_t... i1>
template<typename T2, size_t... i2>
struct Foo<Bar<T1,i1...>,Bar<T2,i2...>>
{
struct Eq {};
};
Run Code Online (Sandbox Code Playgroud)
如您所见,有一种可变参数类型Bar<T,size_t...>和类型Foo<T1,T2>.如果将两个Bars用作模板参数,则Foo具有特殊性.这种专业化具有内在类型Eq.
但是,以下不起作用:
typename Foo<Bar<int,2>,Bar<int,3>>::Eq b;
Run Code Online (Sandbox Code Playgroud)
它讲述的是没有类型Eq的Foo<Bar<int,2>,Bar<int,3>>,即,编译器不挑模板专业化,但基本定义的Foo<T1,T2>这的确没有内在的Eq类型.
我在这做错了什么?为什么编译器不选择专门化?
c++ templates template-specialization variadic-templates c++11
考虑以下代码:
template<typename T,typename K>
struct A{
friend std::ostream& operator<<(std::ostream& out, K x) {
// Do some output
return out;
}
};
int main(){
A<int,int> i;
A<double,int> j;
}
Run Code Online (Sandbox Code Playgroud)
它没有编译,因为A的两个实例化operator<<使用相同的签名实例化了两次,所以我收到了这个错误:
test.cpp:26:25: error: redefinition of ‘std::ostream& operator<<(std::ostream&, int)’
friend std::ostream& operator<<(std::ostream& out, K x) { return out; }
^
test.cpp:26:25: error: ‘std::ostream& operator<<(std::ostream&, int)’ previously defined here
Run Code Online (Sandbox Code Playgroud)
如何解决这个问题?如果该运算符可能具有两个不同实例的相同签名,那么如何在模板中拥有友元运算符?如何在不触发重新定义错误的情况下解决此问题?
测试是否定义了预处理器符号的常用方法是使用#ifdef。但是,#ifdef不能在宏中使用。我需要的是一种检查宏的参数,如果该宏的参数是已定义的预处理程序符号。
例如:
#define TRACE(x,y) if(IS_DEFINED(x)){ std::cout << y; }
Run Code Online (Sandbox Code Playgroud)
在这里,TRACE有两个参数,第一个x应该是预处理器符号的名称。如果定义了此类符号,则应打印第二个参数。IS_DEFINED我正在寻找不存在的功能/宏。
用法如下:
#undef BLA
TRACE(BLA,"abc") // "abc" won't be printed, as BLA is not defined
#define BLA 1
TRACE(BLA,"xyz") // "xyz" will be printed, as BLA is a defined symbol
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点?也许一些宏魔术?当然,该解决方案应该适用于任何符号,不仅适用于符号,也适用于BLA一组硬编码符号。如果要事先知道要检查的符号集,显然很容易。
A有一个制作目标foo/%.bar.它匹配以下文件:
foo/x/y/z.bar
foo/a.bar
现在,我想要一个prereq.o必须与文件位于同一文件夹中的先决条件.bar.因此,对于foo/x/y/z.bar先决条件应该是foo/x/y/prereq.o,foo/a.bar应该是foo/prereq.o.
怎么做到这一点?
我尝试使用这样的dir功能:
foo/%.bar : foo/$(dir %)prereq.o
但是,这不起作用,因为在扩展模式之前评估函数.那么它是怎样工作的?
假设我有以下模板
template <typename T>
class{
T t;
};
Run Code Online (Sandbox Code Playgroud)
现在,我想添加一个构造函数,用它的类型的默认值初始化t.也就是说,对于数值类型,t应初始化为0,对于指针,t应初始化为nullptr.最后,可能还有其他类型的结构.这里,一个好的初始化将是默认的构造函数(无论如何都会被调用,所以我不必在这里做任何事情).
在结论中,我正在寻找这样的事情:
template<typename T>
class X{
T t;
X() : t(default_value<T>::value);
}
Run Code Online (Sandbox Code Playgroud)
正如我想象中的语法指出的那样,我认为使用某种具有不同特殊性的模板可能会带有默认值.但是如何处理结构和类?由于我已经指定t(...),默认构造函数不再是一个选项.
考虑以下代码(godbolt):
#include <optional>
#include <array>
struct LargeType {
std::array<int, 256> largeContents;
};
LargeType doSomething();
std::optional<LargeType> wrapIntoOptional(){
return std::optional<LargeType> {doSomething()};
}
Run Code Online (Sandbox Code Playgroud)
如您所见,有一个函数返回一个大 POD,然后有一个函数将其包装到std::optional. 正如在 godbolt 中可见,编译器memcpy在此处创建了一个,因此它不能完全避免移动对象。为什么是这样?
如果我理解正确的话,C++ 语言将允许由于假设规则而省略移动,因为它没有明显的副作用。看来编译器确实无法避免。但为什么?
我(可能不正确)的理解是编译器如何优化输出,memcpy将对可选内部存储的引用传递给doSomething()(因为我猜这么大的对象无论如何都会通过隐藏引用传递)。wrapIntoOptional由于 RVO,可选本身已经位于调用者的堆栈上。由于 的构造函数的定义std::optional位于标头中,因此编译器可以使用它,因此它应该能够内联它,因此它可以doSomething首先将该存储位置传递给它。那么我的直觉出了什么问题呢?
澄清一下:我并不认为 C++ 语言要求编译器内联它。我只是认为这将是一个合理的优化,并且考虑到将事物包装到可选值中是一种常见的操作,这将是在现代编译器中实现的优化。