我有一个与此问题非常相似的问题.
简而言之,我有一个magic
方法,noexcept
如果是另一种方法noexcept
.
奇怪的是,这个"另一个方法"有两个重载,编译器选择第二个重载来确定magic
noexcept
-ness.
但是,当magic
稍后调用时,会调用第一个重载,但是noexcept
-ness magic
仍然保持不变!
这是wandbox 链接
据我所知:
noexcept(magic(dummy2{}))
电话noexcept(noexcept(adl_caller(...))
这可以追溯到adl_caller(..., priority_tag<0>) noexcept
因为user_method(dummy2)
此时编译器不知道.然而,相当公平,如何user_method(dummy2)
称为3行以上?这是标准的意图吗?
对不起,如果我不够清楚的话.
#include <iostream>
template <unsigned N> struct priority_tag : priority_tag<N - 1> {};
template <> struct priority_tag<0> {};
template <typename T>
auto adl_caller(T t, priority_tag<1>) noexcept(noexcept(user_method(t)))
-> decltype(user_method(t)) {
std::cout << "first adl_caller overload" << std::endl;
user_method(t);
}
// …
Run Code Online (Sandbox Code Playgroud) 我正在阅读这篇博客文章部分,并尝试使用提供的代码段.
namespace N {
// 2
class A {
friend void f(A) {} // 1
};
}
Run Code Online (Sandbox Code Playgroud)
如果我理解正确,那么定义// 1
将注入名称f
所在// 2
的位置.但是它只能通过参数依赖查找来获得.精细.
帖子里有一句引起我注意的句子:
7.3.1.2/3命名空间成员定义[namespace.memdef] p3
首先在名称空间中声明的每个名称都是该名称空间的成员.如果非本地类中的友元声明首先声明了类,函数,类模板或函数模板,则该友元是最内层封闭命名空间的成员.友元声明本身不会使名称对非限定查找(3.4.1)或限定查找(3.4.3)可见.
请注意,没有任何地方声明,友元声明引入的名称必须与声明和/或定义的类的名称有任何特定的关系,或者与该类的任何特定关系(就此而言).
由此,我认为以下代码段是有效的:
namespace N {
struct A {
};
struct B {
friend void f(A) {
}
};
int main() {
N::A a;
f(a);
}
Run Code Online (Sandbox Code Playgroud)
但它被GCC7和Clang 4都拒绝了.
t.cpp:19:3:错误:在此范围内未声明'f'
有趣的是,当我尝试f
使用N::B
对象调用时,我收到以下错误:
t.cpp:12:6:错误:无法将'b'从'N :: B'转换为'N :: A'
所以这是我的问题:
不f(A)
应该通过ADL检测到?由于这两个类都在命名空间中,我不明白为什么会失败.我查看了标准关于朋友的部分,但未找到相关部分.
我想知道f(A)
注入了哪个范围,因为当我尝试通过调用给出错误的参数类型时,GCC能够找到它f(B)
.
我已经尝试构建 mingw-w64 工具链好几天了,但我一直在构建交叉编译器 GCC 8.1.0。
问题是我必须启用线程本地存储 (TLS),因此我传递--enable-tls
给 GCC 的配置脚本。
没有成功,因为在构建结束时,_GLIBCXX_HAVE_TLS
在 中未定义config.h
,对于 也是如此_GLIBCXX_HAVE_CC_TLS
。
我尝试浏览甚至修补自动工具文件以了解如何使其工作。
有人遇到过这个问题吗?
请注意,Windows 上的 mingw-w64 安装程序具有 TLS 符号,因此必须可以为此目标和 TLS 构建 GCC。
我正在尝试做一个我学校的旧项目,它涉及C++ 98中的元编程.我正在努力反对的部分是关于SFINAE.
主题说我应该operator<<
通过使用这样的结构检查流对象和另一个对象之间是否有效:
template<typename Stream, typename Object>
struct IsPrintable;
Run Code Online (Sandbox Code Playgroud)
它说我应该用"两个空引用"写一个奇怪的行,我想它应该是这样的:
sizeof(*(static_cast<Stream *>(NULL)) << *(static_cast<Object *>(NULL)))
Run Code Online (Sandbox Code Playgroud)
它在支持运算符时有效,但在不支持时不运行.我无法弄清楚我失败的地方,这里是文件:
template<typename Flux, typename Object>
struct IsPrintable
{
typedef char yes[1];
typedef char no[2];
template<size_t N>
struct Test
{
typedef size_t type;
};
template<typename U>
static yes &isPrintable(U * = 0);
template<typename>
static no &isPrintable(...);
static const bool value = sizeof(isPrintable<Test<sizeof(*(static_cast<Flux *>(NULL)) << *(static_cast<Object *>(NULL)))> >(0)) == sizeof(yes);
};
Run Code Online (Sandbox Code Playgroud)
主题明确地说使用以size_t作为参数的类,并且isPrintable方法应该采用指向此类实例的NULL指针.另外,使用static_cast的丑陋表达式应该用于类型定义,我试图键入它但是编译器对我尖叫.
我不知道所有内容,因为我对此非常陌生,我知道有一些方法可以简化decltype
操作符,但项目的目的是在C++ 98中完成,如果有的话,它可能很有用.我稍后会找到一些这种类型的代码.
我已经阅读了有关此标准转换的现有问题.但是,我找不到令人满意的答案.
我有这段代码,表明T*
选择了重载T&&
.根据我的理解,转发引用重载应绑定所有内容,除非另一个重载是完美匹配.
在下面的代码中,tab
是一个char const(&)[4]
.
有人可以向我解释为什么在这里执行数组到指针的转换吗?如果有办法解决转换问题,我全都耳朵!
(coliru 链接)
#include <utility>
template <typename T>
void f(T&& lol)
{
}
template <typename T>
void f(T* pof)
{
static_assert(sizeof(T) && false, "");
}
template <typename T>
struct S;
int main(int argc, char *argv[])
{
decltype("lol") tab = "lol";
S<decltype(tab)> s;
f("lol");
return 0;
}
Run Code Online (Sandbox Code Playgroud)