注意:这个问题是关于显式实例化的,而不是显式专业化的。
请看下面的例子:
template <bool A, typename X>
void f (X &x) {} // 1
template <bool A>
void f (int &x) {} // 2
template void f<true> (int &x); // 3
Run Code Online (Sandbox Code Playgroud)
假设我的最初目标是仅显式实例化第二个功能模板,A = true因此我编写line // 3。但是直观上,第一个定义也可以用line显式实例化,// 3这有点麻烦,因为我无法用当前的语法实际转义它,因为bool A在我的情况下无法推断出它。从理论上讲,我什至都不介意两个函数模板最终都被显式实例化,但是最有趣的部分是实际的编译结果。
(在编译成功的所有情况下,仅实例化第二个功能模板。)
原案。用msvc和编译clang。无法使用以下命令进行编译gcc:
错误:“ void f(int&)”的模版模板特殊性“ f”
在第一个功能模板中替换bool A为bool A = truegcc即可对其进行编译。
替换X &x为X &&x(转发参考)会使clang无法使用以下命令进行编译:
错误:“ f”的显式实例化的部分排序不明确
这是最激烈的案例的演示。 …
c++ language-lawyer function-templates explicit-instantiation
当从非模板上下文引用函数模板时,该标准允许在封闭的命名空间范围声明之后或在翻译单元的末尾实例化函数模板:[temp.point]/1
对于函数模板特化、成员函数模板特化或类模板的成员函数或静态数据成员的特化,如果特化是隐式实例化的,因为它是从另一个模板特化和它所在的上下文中引用的引用取决于模板参数,特化的实例化点是封闭特化的实例化点。 否则,这种特化的实例化点紧跟在引用该特化的命名空间范围声明或定义之后。
函数模板、成员函数模板或类模板的成员函数或静态数据成员的特化可能在翻译单元内具有多个实例化点,并且除了上述实例化点之外,对于任何此类在翻译单元内有一个实例化点的特化,翻译单元的结尾也被认为是一个实例化点。类模板的特化在翻译单元内最多有一个实例化点。任何模板的特化都可能在多个翻译单元中具有实例化点。如果根据一个定义规则,两个不同的实例化点赋予模板特化不同的含义,则程序格式错误,无需诊断。
现在考虑这个最小的可重现示例:
#include <iostream>
#include <array>
struct A {};
std::array<char, 2> show(float, A)
{
std::cout << "2\n";
return {};
}
template<typename T>
struct Fun {
decltype(show(0, T{})) b;
};
template <typename T>
void func(T, int c = sizeof(Fun<T>{}.b))
{
show(0, T{});
std::cout << c << '\n';
}
int main()
{
func(A{});
}
char show(int, A)
{
std::cout << "1\n";
return {};
}
Run Code Online (Sandbox Code Playgroud)
GCC 和 Clang 输出1 2(Godbolt)。
在这里,func<A> …
我正在尝试从文件中读取数据,对其进行标记并对其进行排序,但是当我运行它时,strtok表现不正常,有时候它有时它不起作用而且我得到非常短/奇怪的标记.
Valgrind似乎认为这是因为strtok依赖于未初始化的价值(我认为):
== 7069 ==条件跳转或移动取决于未初始化的值
== 7069 ==在0x40B61A3:strtok(strtok.S:160)
== 7069 == by 0x8048842:main(main.c:58)
这是我认为valgrind指责的功能:
char*getNextToken(char*line){
strtokreturn strtok(line,&delim);
}
这可能是因为对于strtok的大多数调用,line是NULL吗?
这是我对函数的调用:
strcpy(performer,getNextToken(inputLine));
strcpy(title,getNextToken(NULL));
strcpy(charMin,getNextToken(NULL));
/etc ... /
我不知道是什么导致了这一点,我给予的所有价值观都是我所期待的.另外我偶尔会得到一个堆栈粉碎错误,我不知道为什么.
我编写了一个 python 脚本,调用 google_images_download 库,以便使用命令行工具从 google 抓取图像。
在我的计算机上,代码运行并下载图像,但是当我使用另一台具有相同脚本的计算机时,它会在标题中提供错误。
我已确保安装了这些库并且其他计算机具有 Python 3。
我尝试使用不同的 wifi 网络看看是否可以解决问题。在我以外的另外两台笔记本电脑上,我遇到了同样的错误。
from google_images_download import google_images_download
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("query")
parser.add_argument("limit", type=int)
args = parser.parse_args()
def download_images(query, limit):
response = google_images_download.googleimagesdownload()
arguments = {"keywords": query,
"limit": limit}
try:
response.download(arguments)
except FileNotFoundError:
arguments = {"keywords": query,
"limit": limit}
try:
response.download(arguments)
except:
pass
def main(query, limit):
download_images(query, limit)
print("Images Printed")
if __name__ == '__main__':
main(args.query, args.limit)
Run Code Online (Sandbox Code Playgroud)
我期望输出创建一个名为 downloads 的文件夹,其中包含一个名为查询名称的子文件夹,并将指定数量的图像放入子文件夹中。
在终端中应该显示正在下载图像 I 到 N。
输出是标题所示的错误代码:
Could not open URL. …Run Code Online (Sandbox Code Playgroud) template <typename T>
void show(T&); // #1
template <typename T>
void show(T const&); // #2
int main()
{
int a = 0;
show(a); // #1 to be called
}
Run Code Online (Sandbox Code Playgroud)
我对这些偏序规则感到困惑。以下是一些引用:[temp.deduct.partial]/5
在完成偏序之前,对用于偏序的类型执行某些转换:
如果
P是引用类型,P则替换为引用的类型。如果
A是引用类型,A则替换为引用的类型。
如果
P和A都是引用类型(在被上面提到的类型替换之前),确定这两种类型中的哪一种(如果有的话)比另一个更符合 cv 限定;否则,出于偏序目的,这些类型被视为同样具有 cv 限定。下面将使用该确定的结果。
删除任何顶级 cv 限定符:
如果
P是 cv 限定类型,P则替换为 的 cv 非限定版本P。如果
A是 cv 限定类型,A则替换为 的 cv 非限定版本A。 …
c++ partial-ordering language-lawyer function-templates template-argument-deduction
由于相关类型IntoIter的的IntoIterator特点,实现了Iterator特质,是不是有足够的推断关联的类型Item?
我有一个我只为练习目的创建的短代码,我想检查如果我有两个catch部分会发生什么,一个是通过引用捕获(int&)而第二个是按值(int)捕获.问题是,当我运行此代码时,即使我抛出"常规"整数,也会出现按引用捕获.为什么会这样?
注意:当我在MSVS17上编译它时,我得到错误C2313:
'int':由第15行的引用('int&')捕获
但是当我使用在线编译器时它工作得很好.
当我删除其中一个catch部分时,即使在MSVS17中它也可以正常工作,但是,为什么是调用引用的catch部分而不是另一个
#include <iostream>
using namespace std;
int main()
{
int i = 5;
try {
if (i)
throw(i);
return 0;
}
catch (int &)
{
cout << "Int&";
}
catch (int)
{
cout << "Int";
}
}
Run Code Online (Sandbox Code Playgroud) 随着即将到来的Ranges库的出现,用两个迭代器来表示一个范围的需求几乎消失了。例如,代替
if (std::equal(begin(foo), end(foo), begin(bar), end(bar)))
Run Code Online (Sandbox Code Playgroud)
我们有
if (std::ranges::equal(foo, bar))
Run Code Online (Sandbox Code Playgroud)
后者之所以可以说是优越的,不仅因为它的简洁性,还因为它避免了忽略end(bar)和欢迎绑定错误的常见陷阱。
下面的代码怎么样?
std::vector<int> vec{begin(foo), end(foo)};
Run Code Online (Sandbox Code Playgroud)
foo范围在哪里。使用Ranges,我希望将其简化为
std::vector<int> vec{foo};
Run Code Online (Sandbox Code Playgroud)
但是,我在[vector]或[container.requirements]中找不到任何提及。Ranges库也没有引入一组新的容器。
为什么Ranges库不支持范围内的容器初始化?理由是什么?
我想存储一些数据,它们可以是仅在运行时才知道的其他类型。我不想浪费任何内存,而是想将所有数据读取为浮点值。在C ++中,我会做这样的事情
struct IA {
virtual float value(int index) = 0;
};
template<class T>
struct A : public IA {
A(T* bytes, uint32_t size) {
values.resize(size);
memcpy(values.data(), bytes, size*sizeof(T));
}
float value(int index) override {
return static_cast<float>(values[index]);
}
std::vector<T> values;
};
int main() {
uint16_t bytes[] = {1, 2, 3, 4, 5 };
IA *a = new A<uint16_t>(bytes, 5);
float value = a->value(0);
delete a;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是如何使用C而不是C ++做到这一点。我可以将数据存储在uint8_t数组中,并存储nr位和一个signed值。然后,每当我从数组中读取一个值时,就使用开关盒和强制类型转换。但是,如果数组很大并且读取次数很多,那将是昂贵的。
我还希望能够在不需要进行任何特殊情况的情况下传递数组?
我的编译器对很多隐式转换感到很温暖:
有些我确实理解,比如
implicit conversion changes signedness: 'int' to 'std::vector::size_type' (aka 'unsigned long')`
Run Code Online (Sandbox Code Playgroud)
当我做myvector.resize(myInt) 。
其他比较晦涩难懂的,比如
implicit conversion loses integer precision: 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::size_type' (aka 'unsigned long') to 'int'
Run Code Online (Sandbox Code Playgroud)
当我这样做时myInt=myString.size(),或者
implicit conversion changes signedness: 'int' to 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::size_type' (aka 'unsigned long')
Run Code Online (Sandbox Code Playgroud)
当我打电话时myString[myInt]
在所有情况下,我确实理解为什么我收到这些消息(int-uint 等),但是它们在程序中的使用是明确的。如果我不更改变量类型来删除这些警告,我会面临什么风险?我以前的编译器没有警告我任何东西,所以当我更换电脑时,我突然收到了几十个警告。
c++ ×6
c ×2
iterator ×2
c++20 ×1
c11 ×1
name-lookup ×1
polymorphism ×1
python ×1
rust ×1
signed ×1
ssl ×1
std ×1
strtok ×1
template-argument-deduction ×1
templates ×1
traits ×1
truncation ×1
valgrind ×1