我正在尝试使用lambdas和编译器,因为这里有另一个问题.
我刚刚意识到(并且确实非常正常)以下代码是有效的:
int main() {
auto l = [](){};
l.operator()();
}
Run Code Online (Sandbox Code Playgroud)
实际上标准说闭包类型有一个公共内联函数调用操作符等等,因此能够调用它是有意义的.
通过查看标准(以及工作草案)我无法解释的是,GCC(6.1)编译了以下代码段(clang 3.9没有):
int main() {
auto l = []<typename>(){};
l.operator()<void>();
}
Run Code Online (Sandbox Code Playgroud)
没有警告,没有错误.它是有效的代码还是被编译器拒绝?
我知道使用static_pointer_cast
with unique_ptr
会导致所包含数据的共享所有权.
换句话说,我想做的是:
unique_ptr<Base> foo = fooFactory();
// do something for a while
unique_ptr<Derived> bar = static_unique_pointer_cast<Derived>(foo);
Run Code Online (Sandbox Code Playgroud)
无论如何,这样做的结果是两个unique_ptr
不应该同时存在,所以它只是被禁止.
是的,绝对有道理,这就是为什么不存在static_unique_pointer_cast
确实存在的原因.
到目前为止,在我想存储指向这些基类的指针的情况下,但我还需要将它们转换为某些派生类(例如,想象一下涉及类型擦除的场景),我使用了shared_ptr
s因为我的'如上所述.
无论如何,我猜测是否有替代方案可以shared_ptr
解决这样的问题,或者在这种情况下它们是否真的是最佳解决方案.
我正在关注如何在C++教程中实现一个常量表达式计数器我正在尝试修复C++ 14没有宏的反射,标记或外部工具..谈话限制.
本教程的基本思想是:
template<int N>
struct flag {
friend constexpr int adl_flag (flag<N>);
};
template<int N>
struct writer {
friend constexpr int adl_flag (flag<N>) { return N; }
static constexpr int value = N;
};
template<int N, class = char[noexcept(adl_flag(flag<N> ()))?+1:-1]>
int constexpr reader (int, flag<N>) { return N; }
template<int N>
int constexpr reader (float, flag<N>, int R = reader (0, flag<N-1>())) { return R; }
int constexpr reader (float, flag<0>) { return …
Run Code Online (Sandbox Code Playgroud) 为了方便起见,我使用了两个库,并在它们使用的某些类型/结构之间编写了一个转换器.
template<typename T>
struct unsupportedType : std::false_type
{};
template<typename T>
FormatB getFormat()
{
static_assert(
unsupportedType<T>::value, "This is not supported!");
}
template<>
FormatB getFormat<FormatA::type1>()
{
return FormatB(//some parameters);
}
template<>
FormatB getFormat<FormatA::type2>()
{
return FormatB(//some other parameters);
}
Run Code Online (Sandbox Code Playgroud)
现在由于unsupportedType
结构,编译器不会立即看到断言将始终失败,因此如果未在某处调用非专用版本,则不会抛出编译错误.但是,编译器因此也不知道返回语句之后static_assert
是不必要的.我不只是想在断言之后放置一个任意的return语句来消除警告.
问题:什么是清除警告的干净方法?
昨天我在SO上看到了一个关于结构化绑定的有趣问题.
我们可以总结如下.请考虑以下示例代码:
#include <tuple>
#include <type_traits>
int main() {
auto tup = std::make_tuple(1, 2);
auto & [ a, b ] = tup;
// the following line won't compile for a isn't a reference
// static_assert(std::is_reference_v<decltype(a)>);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下decltype(a)
是int
(可能),因为这种子弹(工作草案):
if
e
是一个未加括号的id-expression,用于命名结构化绑定[...],decltype(e)
是结构化绑定声明规范中给出的引用类型
这是@Curious在评论中为感兴趣的人提供的wandbox片段.它表明实际上a
不是参考,仅此而已.
到目前为止好于原来的问题,OP问为什么它int
,而不是int &
和标准说,看上去像一个可以接受的答案.
无论如何,我想知道委员会为何如此决定.在一天结束时,a
引用元组中的元素,我可以通过修改该元素a
.换句话说,声明a
看起来像一个引用,它的行为类似于引用,但它不是引用.
我可以忍受这个,但我想知道背后的原因是什么.为什么decltype(a)
不能简单int &
?亵渎者可以理解是否有一个有意义的理由?
我需要实现std::map
与<std::string, fn_ptr>
对.函数指针是指向拥有映射的同一类的方法的指针.我们的想法是直接访问方法,而不是实现交换机或等效方法.
(我std::string
用作地图的键)
我对C++很陌生,所以有人会发布一些伪代码或链接来讨论用函数指针实现一个映射吗?(指向拥有地图的同一个类所拥有的方法的指针)
如果您认为我的问题有更好的方法,也欢迎提出建议.
这是对这个问题的跟进.
如答案评论中所述:
内联变量具有以下属性: - 在每个转换单元中具有相同的地址.[...]通常您通过在cpp文件中定义变量来实现这一点,但是使用内联说明符,您只需在头文件中声明/定义变量,并且使用此内联变量的每个转换单元都使用完全相同的对象.
而且,从答案本身来说:
虽然该语言不保证(甚至提及)在跨共享库边界使用此新功能时会发生什么,但它确实可以在我的计算机上运行.
换句话说,当涉及共享库时,不清楚内联变量是否保证跨边界是唯一的.有人在经验证明它可以在某些平台上运行,但它不是一个正确的答案,它可能只是破坏其他平台上的一切.
内联变量在跨越边界使用时是否有任何保证,或者它只是一个我不应该依赖的实现细节?
考虑以下结构:
struct S {};
Run Code Online (Sandbox Code Playgroud)
在C++ 14中,以下定义是有效的:
constexpr auto f() { return S{}, 'c'; }
Run Code Online (Sandbox Code Playgroud)
以及以下一个:
constexpr auto f() { return S{}, void(); }
Run Code Online (Sandbox Code Playgroud)
现在,请考虑以下涉及两个定义中的第一个的工作代码段:
#include<type_traits>
struct S {};
constexpr int operator,(S, char) { return 42; }
constexpr auto f() { return S{}, 'c'; }
int main() {
constexpr int i{f()};
static_assert(i == 42, "!");
static_assert(std::is_same<decltype(f()), int>::value, "!");
}
Run Code Online (Sandbox Code Playgroud)
说来不是技术上的,逗号运算符的重载拦截了这对,S{}, 'c'
并返回一个整数,正如在main
函数中正确验证的那样.
现在,假设我想对第二个定义做同样的事情f
:
constexpr auto f() { return S{}, void(); }
Run Code Online (Sandbox Code Playgroud)
在这种情况下,逗号运算符应截取表单 …
c++ operator-overloading void comma-operator language-lawyer
我有一个类必须依赖于int
模板参数的某些原因.
出于同样的原因,该参数不能成为类的参数列表的一部分,而是它的构造函数的参数列表的一部分(当然,模板化).
这里出现了问题.
也许我错过了一些东西,但是我看不到向构造函数提供这样一个参数的简单方法,因为它不能推断也不能明确指定.
到目前为止,我发现了以下替代方案:
将上述参数放入类的参数列表中
创建工厂方法或工厂函数,可以作为示例调用 factory<42>(params)
为构造函数提供traits结构
我试图为最后提到的解决方案创建一个(不那么)最小的工作示例,以便更好地解释问题.
示例中的类不是自身的模板类,因为关键点是构造函数,无论如何真正的模板类是模板类.
#include<iostream>
#include<array>
template<int N>
struct traits {
static constexpr int size = N;
};
class C final {
struct B {
virtual ~B() = default;
virtual void foo() = 0;
};
template<int N>
struct D: public B{
void foo() {
using namespace std;
cout << N << endl;
}
std::array<int, N> arr;
};
public:
template<typename T>
explicit C(T) {
b = new D<T::size>{};
}
~C() …
Run Code Online (Sandbox Code Playgroud) 请考虑以下代码段:
auto f() { return void({}); }
int main() { f(); }
Run Code Online (Sandbox Code Playgroud)
什么是完全{}
的void({})
?
怎么解释?
当然,只是出于好奇.不管怎样,让我们走得更远.
请注意,GCC 6.1和clang 3.8都编译它没有错误(-std=c++14 -pedantic
).
后者没有抱怨,前者显示警告:
警告:非类类型的list-initializer不能带括号
使用-pedantic-errors
替代,GCC有错误而铛编译结束.
这种差异是否是两个编译器之一的错误?
我的意思是,它是否应该被接受的有效代码?