我试图理解类型衰变的本质.例如,我们都知道数组在特定上下文中衰减为指针.我的尝试是了解如何int[]等同于int*二维数组如何与预期的指针类型不对应.这是一个测试用例:
std::is_same<int*, std::decay<int[]>::type>::value; // true
Run Code Online (Sandbox Code Playgroud)
这会按预期返回true,但这不会:
std::is_same<int**, std::decay<int[][1]>::type>::value; // false
Run Code Online (Sandbox Code Playgroud)
为什么这不是真的?我终于找到了一种让它返回true的方法,那就是让第一个维度成为一个指针:
std::is_same<int**, std::decay<int*[]>::type>::value; // true
Run Code Online (Sandbox Code Playgroud)
对于任何带指针的类型,断言都适用,但最后一个是数组.例如(int***[] == int****; // true).
我可以解释为什么会这样吗?为什么数组类型不符合预期的指针类型?
如何创建一个类模板,返回其任何可变类型是否等于第一个类型.我希望能够这样做:
is_same<T, A, B, C>::value; // true if T is one of A, B or C
Run Code Online (Sandbox Code Playgroud)
如果T等于这些类型中的任何一个,则其静态value成员将是true,否则false.我怎样才能做到这一点?
我正在尝试使用此代码来演示复制构造函数的用法.我的假设是,当我有一个按值返回的函数时,默认情况下,我的编译器将执行对象的移动.但是当move-constructor不可用时,编译器将复制(在C++ 03中,编译器在返回by-value时会复制).那么为什么在下面的例子中编译器会尝试调用显式删除的move-constructor而不是可用的copy-constructor呢?我在GCC 4.7.2中编译了这个.
struct S
{
S() = default;
S(S const &) = default;
S(S&&) = delete;
};
S f() { return S{}; }
int main()
{
f();
}
Run Code Online (Sandbox Code Playgroud)
prog.cpp:在函数中
‘S f()’:
prog.cpp:8:18:错误:使用已删除的函数‘S::S(S&&)’
prog.cpp:5:5:错误:在此声明
这样做有什么区别:
X() = default;
Run Code Online (Sandbox Code Playgroud)
和
constexpr X() = default;
Run Code Online (Sandbox Code Playgroud)
默认构造常量表达式中的类工作正常,这两个例子之间有区别吗?我应该使用一个吗?
如何创建一个返回类型sizeof大于其他类型的类模板.例如:
typename largest<int, char, double>::type;
Run Code Online (Sandbox Code Playgroud)
那会回来double.我该怎么做呢?
如何反转元组中的类型?例如,我想reverse_tuple<std::tuple<int, char, bool>>::type成为std::tuple<bool, char, int>.我尝试了以下但是没有用.我做错了什么?
#include <type_traits>
#include <tuple>
template <typename... Ts>
struct tuple_reverse;
template <typename T, typename... Ts>
struct tuple_reverse<std::tuple<T, Ts...>>
{
using type = typename tuple_reverse<
std::tuple<
typename tuple_reverse<std::tuple<Ts..., T>>::type
>
>::type;
};
template <typename T>
struct tuple_reverse<std::tuple<T>>
{
using type = std::tuple<T>;
};
int main()
{
using result_type = std::tuple<int, bool, char>;
static_assert(
std::is_same<
tuple_reverse<var>::type, std::tuple<char, bool, int>
>::value, ""
);
}
Run Code Online (Sandbox Code Playgroud)
这是我的错误:
prog.cpp: In instantiation of ‘struct tuple_reverse<std::tuple<char, int, bool> >’:
prog.cpp:15:34: …
这是类的移动构造函数X:
X::X(X&& rhs)
: base1(std::move(rhs))
, base2(std::move(rhs))
, mbr1(std::move(rhs.mbr1))
, mbr2(std::move(rhs.mbr2))
{ }
Run Code Online (Sandbox Code Playgroud)
这些是我警惕的事情:
rhs 两次,并rhs不能保证在一个有效的状态.是不是初始化的未定义行为base2?rhs到mbr1和mbr2,但由于rhs已经从移动(并再次,它不能保证是一个有效的状态)为什么要做这项工作?这不是我的代码.我在一个网站上找到了它.这个移动构造函数安全吗?如果是这样,怎么样?
这段代码发生了什么?太令人困惑了.
#include <utility>
struct check
{
template <typename T>
auto foo() -> decltype(std::declval<T>().value, void())
{
static_assert(T{}.value == 10, "Incorrect value");
}
} var;
int main()
{
struct apple
{
int value{10};
};
var.foo<apple>();
}
Run Code Online (Sandbox Code Playgroud)
特别是它所拥有的部分->以及之后的一切.
我之前看过这样的代码:
using A = std::vector<std::vector<T>...>
Run Code Online (Sandbox Code Playgroud)
其中T是模板参数的可变参数列表.我想知道将参数包放在最后一个尖括号的末尾和第一个尖括号之间有什么区别.例如:
using B = std::vector<std::vector<T...>>;
Run Code Online (Sandbox Code Playgroud)
这两个编译都很好,但我不知道有什么区别.
谁能解释一下?谢谢.
我在一周前询问了一个问题,询问如何只在它所采用的类型具有特定成员函数时才能简单地实例化一个类模板.在我的回答中,我得到了一个复杂的解决方案.但后来我试着自己做.我只是想知道这是否足以弄清楚给定类型T是否有一个名为ftake 0参数的void函数.
#include <type_traits>
#include <utility>
template <typename T, typename = void>
struct has_f : std::false_type { };
template <typename T>
struct has_f<
T,
decltype(std::declval<T>().f(), void())> : std::true_type { };
template <typename T, typename = typename std::enable_if<has_f<T>::value>::type>
struct A { };
struct B
{
void f();
};
struct C { };
template class A<B>; // compiles
template class A<C>; // error: no type named ‘type’
// in ‘struct std::enable_if<false, void>’
Run Code Online (Sandbox Code Playgroud)