相关疑难解决方法(0)

C++ 模板 - 完整指南:了解有关 decltype 和返回类型的脚注注释

C++ 模板第二版- 完整指南在第 435 页包含以下代码

#include <string>
#include <type_traits>

template<typename T, typename = void>
struct HasBeginT : std::false_type {};

template<typename T>
struct HasBeginT<T, std::void_t<decltype(std::declval<T>().begin())>>
    : std::true_type {};
Run Code Online (Sandbox Code Playgroud)

和用于测试调用 adecltype(std::declval<T>().begin())是否有效的注释。.begin()T

这一切都有道理,我想……

令我震惊的是脚注中的评论:

除此之外,与其他上下文中的调用表达式不同,它不需要非引用、非返回类型来完成。使用相反,确实增加了调用返回类型完整的要求,因为返回值不再是操作数的结果。decltype(call-expression)voiddecltype(std::declval<T>().begin(), 0)decltype

我不太明白。

为了尝试使用它,我尝试使用以下代码查看它对voidmember的行为begin

struct A {
    void begin() const;
};

struct B {
};

static_assert(HasBeginT<A>::value, "");
static_assert(!HasBeginT<B>::value, "");
Run Code Online (Sandbox Code Playgroud)

但无论有没有 . ,这两个断言都通过了, 0

c++ templates decltype c++17 void-t

12
推荐指数
1
解决办法
455
查看次数

为什么我们不能在未评估的上下文中使用大括号初始值设定项?

我最近看到一些基于SFINAE的代码如下所示:

template <typename T>
auto test(T &myclass) -> decltype(myclass.f(), void()) 
{
    // do something here, don't return anything (void)
}
Run Code Online (Sandbox Code Playgroud)

基本上上面的函数使用SFINAE来拒绝所有T没有f()作为成员函数的类型的参数.SFINAE发生在decltype我们有两个用逗号运算符分隔的表达式的地方.如果无法评估第一个表达式,SFINAE会启动并拒绝过载.如果可以计算表达式,那么,由于逗号运算符,void正在从函数返回.

据我明白,void()"构建体"一个void处于未评估上下文对象(是的,这是合法的),然后由所拾取decltype所以void是该函数的返回类型.

我的问题是:为什么我们不能使用void{}呢?它是否具有void在未评估的上下文中"构造" 对象的相同效果?我的编译器(g ++/clang ++)不接受void{}代码

error: compound literal of non-object type 'void' (克++ 4.9 /克++ 5)

error: illegal initializer type 'void' (clang ++ 3.5)

c++ decltype sfinae c++11

9
推荐指数
1
解决办法
265
查看次数

如何从自动退货类型中推断出类型?

这个答案有一个这样的代码片段:

template<class T, class F>
auto f(std::vector<T> v, F fun)
    -> decltype( bool( fun(v[0] ) ), void() )
{
  // ...
}
Run Code Online (Sandbox Code Playgroud)

它真正编译和工作(至少在Ideone上).

那么,在这种情况下如何推断出类型?

c ++ 11标准真的允许下一行吗?

decltype( bool( fun(v[0] ) ), void() )
Run Code Online (Sandbox Code Playgroud)

我快速浏览了一下,看起来并不合适.在这种情况下,意识错误吗?


c ++ 11标准中的所有示例都是这样的,它们在decltype中只有一种类型:

struct A {
  char g();
  template<class T> auto f(T t) -> decltype(t + g())
  { return t + g(); }
};
Run Code Online (Sandbox Code Playgroud)

另一个例子 :

void f3() {
  float x, &r = x;
  [=] {
  decltype(x) y1;
  decltype((x)) y2 = y1; …
Run Code Online (Sandbox Code Playgroud)

c++ decltype c++11

8
推荐指数
2
解决办法
851
查看次数

SFINAE:'static_cast <void>()'或',void()'?

在任意类型上执行SFINAE时,通常需要将表达式的结果转换为void.我已经看到了两种方法; 演员无效:

(void)(expr)    // or static_cast<void>(expr)
Run Code Online (Sandbox Code Playgroud)

或者,使用带有void prvalue RHS的逗号运算符:

(expr), void()
Run Code Online (Sandbox Code Playgroud)

我的理解是,在两种情况下都要expr评估(对于良好的形式,在非评估的上下文中)和结果(或结果类型,在非评估的上下文中)被丢弃; 在任何一种情况下,即使是病理类也不可能T覆盖T::operator void()operator,(T, void).(参见:为什么是"运营商无效"不投语法调用?,什么的'无效()'中的'自动F(PARAMS) - > decltype(...,无效())'呢?).

也就是说,这两个成语是等价的,还是在某种情况下,一个人应该优先于另一个(可能是非标准的编译器)?如果没有,是否有任何理由(例如可理解性)偏好一个而不是另一个?

c++ void decltype sfinae

8
推荐指数
1
解决办法
316
查看次数

c ++ 11 decltype返回引用类型

我有点困惑为什么decltype逗号运算符在某些情况下返回引用类型.

例如,在此代码中:

int i = 101;
decltype(1, i) var = i;
var = 20;
printf("%d\n", i); // will print 20
Run Code Online (Sandbox Code Playgroud)

这里,var是int而不是int,但如果我用第二行替换:

decltype(i) var = i;
Run Code Online (Sandbox Code Playgroud)

它将返回int!

任何人都可以解释一下吗?

c++ decltype c++11

4
推荐指数
1
解决办法
163
查看次数

如何使用 sfinae 排除定义了函数的类型?

考虑如何使用decltype()尾随返回类型中的逗号表达式来检查是否可以应用函数:

template <class A>
auto f(A a) -> decltype(check_if_possible(a), return_type(a))
Run Code Online (Sandbox Code Playgroud)

如何否定逗号前的部分以排除check_if_possible(a)已定义的情况?

上下文: f()是不同的重载函数A。我想解决两个实现之间的歧义重载。其中一个使用check_if_possible(a),另一个在不能应用的情况下工作a

编辑:std::enable_if也欢迎使用和相关的东西,但我想避免额外的辅助功能/模板,因为有几个功能类似于f()具有不同启用条件的功能。如果这是不可能的,那么这也是一个答案;)

c++ decltype sfinae trailing-return-type

4
推荐指数
1
解决办法
85
查看次数

标签 统计

c++ ×6

decltype ×6

c++11 ×3

sfinae ×3

c++17 ×1

templates ×1

trailing-return-type ×1

void ×1

void-t ×1