我有以下案例可以使用std::enable_if:
template<typename T,
typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr>
void f() { }
template<typename T,
typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr>
void f() { }
Run Code Online (Sandbox Code Playgroud)
现在,我在cppreference中看到了新的语法,在我看来更加清晰: typename = std::enable_if_t<std::is_same<int, T>::value>>
我想移植我的代码:
template<typename T,
typename = std::enable_if_t<std::is_same<int, T>::value>>
void g() { }
template<typename T,
typename = std::enable_if_t<std::is_same<double, T>::value>>
void g() { }
Run Code Online (Sandbox Code Playgroud)
但现在海湾合作委员会(5.2)抱怨:
error: redefinition of 'template<class T, class> void g()'
void g() { }
Run Code Online (Sandbox Code Playgroud)
为什么会这样 ?如果可能,我该怎么做才能在这种情况下使用新的,更简洁的语法?
假设我有一个template功能:
template<typename T>
T produce_5_function() { return T(5); }
Run Code Online (Sandbox Code Playgroud)
我怎么能将这整个传递template给另一个template?
如果produce_5_function是仿函数,那就没有问题:
template<typename T>
struct produce_5_functor {
T operator()() const { return T(5); }
};
template<template<typename T>class F>
struct client_template {
int operator()() const { return F<int>()(); }
};
int five = client_template< produce_5_functor >()();
Run Code Online (Sandbox Code Playgroud)
但我希望能够使用原始函数模板执行此操作:
template<??? F>
struct client_template {
int operator()() const { return F<int>(); }
};
int five = client_template< produce_5_function >()();
Run Code Online (Sandbox Code Playgroud)
我怀疑答案是"你不能这样做".
我有一个函数,它接受一个数字并返回那么多东西(比方说,整数).什么是最干净的界面?一些想法:
vector<int>.矢量将被复制多次,这是低效的.vector<int>*.我的getter现在必须分配向量本身以及元素.有谁必须释放向量的所有常见问题,你不能分配一次并使用相同的存储器来进行对getter的许多不同调用等.这就是为什么STL算法通常避免分配内存,而是想要它传入了.unique_ptr<vector<int>>.现在很清楚是谁删除了它,但我们还有其他问题.vector<int>作为参考参数.getter可以push_back()和调用者决定是否到reserve()空间.但是,如果传入vector非空,那么getter应该怎么做?附加?通过先清除它来覆盖?断言它是空的?如果函数的签名只允许一个解释,那将是很好的.begin和end迭代器.现在我们需要返回实际写入的项目数(可能小于预期),并且调用者需要注意不要访问从未写入的项目.iterator,呼叫者可以通过insert_iterator.char *.:)所有报价均来自N3797.
4/3 [转]
当且仅当声明T t = e时,表达式e可以隐式转换为类型T. 对于一些发明的临时变量t而言,其形式良好
这意味着没有表达式可以隐式转换为void,这void t=e对所有表达式都是非法的e.如果e是类型的表达式void,例如,这甚至是真的void(3).
所以类型的表达式void不能隐式转换为void.
这导致我们:
20.9.2/2要求[func.require]
将INVOKE(f,t1,t2,...,tN,R)定义为隐式转换为R的INVOKE(f,t1,t2,...,tN).
总之,INVOKE(f, t1, t2, ..., tN, R)当是永远有效R的void,如无(含void)可以隐式转换为void.
因此,所有都std::function<void(Args...)>具有属性!*this,因此不能被调用,因为唯一没有!*this后置条件的构造函数(或者不从function相同类型的另一个复制此类状态)需要Callable其中一个参数.
20.9.11.2/7类模板函数[func.wrap.func]
要求:F应为CopyConstructible.对于参数类型ArgTypes,f应为Callable(20.9.11.2)并返回R类型.A的拷贝构造函数和析构函数不应抛出异常.
20.9.11.2/2类模板函数[func.wrap.func]
类型F的可调用对象f对于参数类型ArgTypes是Callable,如果表达式INVOKE(f,declval()...,R)被认为是未评估的操作数(第5条),则返回类型R( 20.9.2).
如上所述,没有Callable表达std::function<void(Args...)>.
如果以某种方式std::function<void(Args...)>找到这样的地方,调用operator()将会形成错误:
调用[func.wrap.func.inv]
效果:INVOKE(f,std :: forward(args)...,R)(20.9.2),其中f是*this的目标对象(20.9.1).
因为INVOKE(f, …
所以我想写一个自动的!=:
template<typename U, typename T>
bool operator!=(U&& u, T&& t) {
return !( std::forward<U>(u) == std::forward<T>(t) );
}
Run Code Online (Sandbox Code Playgroud)
但这是不礼貌的1.所以我写
// T() == U() is valid?
template<typename T, typename U, typename=void>
struct can_equal:std::false_type {};
template<typename T, typename U>
struct can_equal<
T,
U,
typename std::enable_if<
std::is_convertible<
decltype( std::declval<T>() == std::declval<U>() ),
bool
>::value
>::type
>: std::true_type {};
Run Code Online (Sandbox Code Playgroud)
这是一个类型traits类,它表示"是t == u返回可转换为的类型的有效代码bool".
所以我改进了!=:
template<typename U, typename T,
typename=typename std::enable_if<can_equal<T,U>::value>::type
>
bool operator!=(U&& u, T&& …Run Code Online (Sandbox Code Playgroud) 在C++ 14中,什么是一种理解函数或函数对象的好方法?
特别是,我有一个foo带有一些随机数量的重载的重载函数:可以通过ADL找到一些重载,其他的可以在无数个地方定义.
我有一个帮助对象:
static struct {
template<class...Args>
auto operator()(Args&&...args)const
-> decltype(foo(std::forward<Args>(args)...))
{ return (foo(std::forward<Args>(args)...));}
} call_foo;
Run Code Online (Sandbox Code Playgroud)
这让我可以将重载集作为单个对象传递.
如果我想要咖喱foo,我该怎么办呢?
由于curry和部分功能应用程序经常互换使用,curry我的意思是,如果foo(a,b,c,d)是有效的呼叫,那么curry(call_foo)(a)(b)(c)(d)必须是有效的呼叫.
我想问题就是这一切,但是,如果有人关闭c ++控制台应用程序会发生什么?如上所示,单击顶角的"x".它会立即关闭吗?它会引发某种异常吗?是不确定的行为?
所以,假设我想使用类型擦除键入erase.
我可以为支持自然的变体创建伪方法:
pseudo_method print = [](auto&& self, auto&& os){ os << self; };
std::variant<A,B,C> var = // create a variant of type A B or C
(var->*print)(std::cout); // print it out without knowing what it is
Run Code Online (Sandbox Code Playgroud)
我的问题是,如何将其扩展为std::any?
它不能在"原始"中完成.但是在我们分配给/构建一个std::any我们需要的类型信息时.
所以,从理论上讲,增强了any:
template<class...OperationsToTypeErase>
struct super_any {
std::any data;
// or some transformation of OperationsToTypeErase?
std::tuple<OperationsToTypeErase...> operations;
// ?? what for ctor/assign/etc?
};
Run Code Online (Sandbox Code Playgroud)
可以某种方式自动重新绑定一些代码,以便上述类型的语法可以工作.
理想情况下,它与使用变体的情况一样简洁.
template<class...Ops, class Op,
// SFINAE filter that an op matches:
std::enable_if_t< std::disjunction< std::is_same<Ops, …Run Code Online (Sandbox Code Playgroud) 看起来我们正在为C++获得全新的"面试问题"(我希望不是,实际上).
众所周知,在C++ 17之前,它是未定义的行为,但它是否会从C++ 17开始明确定义?
由于目前似乎没有一个编译器实现了这个C++ 17修改,根据表达式评估规则,任何人都可以解释x在下面的代码中的值是什么?
int i = 0;
int x = i++ + i++;
Run Code Online (Sandbox Code Playgroud)
阿利斯代尔梅雷迪思提到这个例子在这里他CppCon 2016的谈话,但它并不完全清楚,我的最终值什么x会(虽然它似乎什么他要说的是,这将是至少1).
显然,i在这种情况下,本身将在表达式结尾处为2.
c++ operator-precedence undefined-behavior language-lawyer c++17
在计算机科学中,有两个难题:缓存失效,命名和一个错误。
这是关于第二个问题的:命名事物。
我在寻找这种技术或类型是否已经在其他地方使用并且有名称。 dichotomy是一个不错的名字,但那bools_at_compile_time是一个可怕的名字。
using dichotomy_t = std::variant<std::false_type, std::true_type>;
// (or a struct that inherits from that, and overloads operator bool())
constexpr dichotomy_t dichotomy( bool b ) {
if (b) return std::true_type{};
return std::false_type{};
}
template<class F, class...Bools>
constexpr auto bools_at_compile_time( F&& f, Bools...bools ) {
static_assert( (std::is_same<Bools, bool>{} && ...) );
return std::visit( std::forward<F>(f), dichotomy(bools)... );
}
Run Code Online (Sandbox Code Playgroud)
dichotomy_t是true和false之间的变体。其运行时表示为0或1。
这可以让您做的是:
auto foo( bool x, bool y ) { // <-- x and …Run Code Online (Sandbox Code Playgroud)