适用于类的语法不适用于概念:
template <class Type>
concept C = requires(Type t) {
// ...
};
template <class Type>
concept C<Type*> = requires(Type t) {
// ...
};
Run Code Online (Sandbox Code Playgroud)
MSVC 对于“专业化”行的说法是:error C7606: 'C': concept cannot be explicitly instantiated, explicitly specialized or partially specialized
。
为什么概念不能专门化?有理论上的原因吗?
我最近安装了 Visual Studio 和 Visual Studio Code,这两个 .dll 文件留在我的C:\
文件夹中。两者均由微软签署。他们在那里有什么理由吗?它们可以移动或删除吗?
这些文件是:
C:\appverifUI.dll
C:\vfcompat.dll
Visual Studio 和 Visual Studio Code 都是官方网站的最新版本。
我认为它们是安装过程中留下的,应该由安装程序移动/删除,但我不确定。
考虑以下示例:
struct vector {
int size() const;
bool empty() const;
};
bool vector::empty() const
{
return size() == 0;
}
Run Code Online (Sandbox Code Playgroud)
生成的汇编代码vector::empty
(通过 clang,经过优化):
push rax
call vector::size() const
test eax, eax
sete al
pop rcx
ret
Run Code Online (Sandbox Code Playgroud)
为什么要分配堆栈空间?它根本没有被使用。该push
和pop
可以省略。MSVC 和 gcc 的优化构建也为此功能使用堆栈空间(请参阅有关Godbolt 的内容),因此必须有一个原因。
假设我们有以下程序:
template <class T, T n1, T n2>
struct Probe {
static const int which = 1;
};
template <class T, T n>
struct Probe<T, n, n> {
static const int which = 2;
};
int i = 123;
const int myQuestion = Probe<int&, i, i>::which;
Run Code Online (Sandbox Code Playgroud)
我很确定,这myQuestion
应该2
与 C++ 标准的版本无关,但编译器不同意这一点。MSVC 和 clang 表示,2
C++14 之前,1
C++17 以后。请参阅演示。真相是什么?
到目前为止我的调查:
c++ template-specialization c++14 c++17 non-type-template-parameter
我知道,许多类型(例如 POD 类型)都是默认可构造的。但是除了空参数列表之外,哪些类型可以从参数列表轻松构造?例如,什么类型可以简单地从 构造出来int
?我想不出任何一个。
int
以下类型在 C++17 中不能轻易构造(现场演示):
#include <type_traits>
struct X { int x; };
struct Y { Y(int) {} };
struct Z { Z(int) = delete; };
static_assert(std::is_trivially_constructible<X, int>::value == false);
static_assert(std::is_trivially_constructible<Y, int>::value == false);
static_assert(std::is_trivially_constructible<Z, int>::value == false);
Run Code Online (Sandbox Code Playgroud) 以下代码使用MSVC和gcc进行编译,但不能使用clang进行编译。为什么?
如果CallFoo ()
is的话,似乎ADL无法正常工作constexpr
。查看评论。
template <class T>
constexpr void CallFoo () // Remove constexpr to fix clang compilation error.
{
Foo (T ());
}
class Apple {};
int main ()
{
CallFoo<Apple> ();
}
constexpr void Foo (Apple)
{
}
Run Code Online (Sandbox Code Playgroud)
Clang错误消息(请参阅godbolt.org):
<source>:4:5: error: use of undeclared identifier 'Foo'
Foo (T ());
^
<source>:13:5: note: in instantiation of function template specialization 'CallFoo<Apple>' requested here
CallFoo<Apple> ();
^
Run Code Online (Sandbox Code Playgroud) 模板中使用的从属名称的查找被推迟到知道模板参数为止,这时ADL会检查具有外部链接的函数声明,这些声明从模板定义上下文或模板实例化上下文中可见。
与此相反,以下代码片段可以使用三个编译器(MSVC,clang和gcc)很好地进行编译:
template <class T>
void CallFoo ()
{
Foo (T ());
}
class Apple {};
int main ()
{
CallFoo<Apple> ();
}
static void Foo (Apple)
{
}
Run Code Online (Sandbox Code Playgroud)
Foo
是以下内容中的从属名称CallFoo
:它取决于模板参数T
。但是,Foo
尽管违反了上面引用的两个规则,但是编译器仍然可以找到该函数。
Foo
从的定义或实例中都看不到的声明CallFoo
,因为它位于两者之下。Foo
有内部联系。这三个编译器都不可能有错误。我可能误会了一些东西。您能详细说明一下吗?
c++ linkage dependent-name language-lawyer argument-dependent-lookup
在以下程序中,全局变量isCompleteType<Apple>
由 clang 和 gcc 以不同的方式初始化(位于Godbolt.org 上):
template <class T>
constexpr bool IsCompleteTypeHelper (decltype (sizeof (T))) { return true; }
template <class T>
constexpr bool IsCompleteTypeHelper (...) { return false; }
template <class T>
bool isCompleteType = IsCompleteTypeHelper<T> (0);
class Apple;
int main ()
{
return isCompleteType<Apple>;
}
class Apple {};
Run Code Online (Sandbox Code Playgroud)
isCompleteType<Apple>
为true
.isCompleteType<Apple>
为false
.由于Apple
可以生成变量的定义true
是在的实例化之后isCompleteType
,因此我得出结论,编译器在初始化变量时会执行以下操作。
c++ language-lawyer incomplete-type variable-templates c++14
struct myclass {
myclass(){}
myclass(int qx):z(qx){ }
std::function<void()> create() {
auto px = [z](){
std::cout << z << std::endl;
};
return px;
}
int z;
};
myclass my;
my.z = 2;
auto func = my.create();
func();
my.z = 3;
func();
Run Code Online (Sandbox Code Playgroud)
这段代码将在 gcc 4.6.3 中编译,它会做正确的事情来制作成员变量的副本z
,并且两个 print 都会得到2
. 在 gcc 4.8.2 这不再编译..
error: 'this' was not captured for this lambda function
Run Code Online (Sandbox Code Playgroud)
我想知道为什么这个功能被删除了,因为它非常有用。
为什么在+
使用运算符语法调用一元时会收到错误消息?如果我用函数语法调用它,就可以了。现场演示。
template <int size>
struct Buffer { char buf[size]; };
template <class T>
struct Wrapper { void operator+() {} };
Wrapper<Buffer<-5>> a;
void f1() { +a; } // error: Buffer<-5>::buf has negative size
void f2() { a.operator+(); } // OK
Run Code Online (Sandbox Code Playgroud) c++ ×9
c++14 ×2
templates ×2
abi ×1
c++-concepts ×1
c++11 ×1
c++17 ×1
c++20 ×1
clang ×1
constexpr ×1
g++ ×1
linkage ×1
non-type-template-parameter ×1
type-traits ×1