小编Yak*_*ont的帖子

为什么模板参数中的enable_if_t会抱怨重定义?

我有以下案例可以使用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)

为什么会这样 ?如果可能,我该怎么做才能在这种情况下使用新的,更简洁的语法?

c++ templates sfinae enable-if c++14

29
推荐指数
2
解决办法
2万
查看次数

如何在模板参数列表中传递模板函数

假设我有一个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)

我怀疑答案是"你不能这样做".

c++ templates function-templates c++11

27
推荐指数
2
解决办法
7212
查看次数

返回一堆值的接口

我有一个函数,它接受一个数字并返回那么多东西(比方说,整数).什么是最干净的界面?一些想法:

  1. 回来一个vector<int>.矢量将被复制多次,这是低效的.
  2. 回来一个vector<int>*.我的getter现在必须分配向量本身以及元素.有谁必须释放向量的所有常见问题,你不能分配一次并使用相同的存储器来进行对getter的许多不同调用等.这就是为什么STL算法通常避免分配内存,而是想要它传入了.
  3. 回来一个unique_ptr<vector<int>>.现在很清楚是谁删除了它,但我们还有其他问题.
  4. 以a vector<int>作为参考参数.getter可以push_back()和调用者决定是否到reserve()空间.但是,如果传入vector非空,那么getter应该怎么做?附加?通过先清除它来覆盖?断言它是空的?如果函数的签名只允许一个解释,那将是很好的.
  5. 传递一个beginend迭代器.现在我们需要返回实际写入的项目数(可能小于预期),并且调用者需要注意不要访问从未写入的项目.
  6. 让吸气者接受iterator,呼叫者可以通过insert_iterator.
  7. 放弃,只是通过一个char *.:)

c++ c++11 c++98

27
推荐指数
2
解决办法
1794
查看次数

在标准下调用std :: function <void(Args ...)>是违法的吗?

所有报价均来自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)当是永远有效Rvoid,如无(含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, …

c++ language-lawyer c++11 std-function c++14

27
推荐指数
1
解决办法
863
查看次数

在SFINAE模板中如何避免这句话是假的?

所以我想写一个自动的!=:

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++ templates operator-overloading sfinae c++11

26
推荐指数
1
解决办法
882
查看次数

我该如何制作咖喱功能?

在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++ templates overloading currying c++14

25
推荐指数
2
解决办法
3458
查看次数

关闭c ++控制台应用程序时会发生什么

我想问题就是这一切,但是,如果有人关闭c ++控制台应用程序会发生什么?如上所示,单击顶角的"x".它会立即关闭吗?它会引发某种异常吗?是不确定的行为?

c++ winapi console-application

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

键入擦除类型擦除,"任何"问题?

所以,假设我想使用类型擦除键入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++ type-erasure c++17 stdany

24
推荐指数
2
解决办法
2000
查看次数

我将用++ + i ++在C++ 17中评估什么?

看起来我们正在为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

24
推荐指数
1
解决办法
878
查看次数

该类型和功能是否已有名称?

在计算机科学中,有两个难题:缓存失效,命名和一个错误。

这是关于第二个问题的:命名事物。

我在寻找这种技术或类型是否已经在其他地方使用并且有名称。 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之间的变体。其运行时表示为01

这可以让您做的是:

auto foo( bool x, bool y ) { // <-- x and …
Run Code Online (Sandbox Code Playgroud)

c++ boolean variant c++17

24
推荐指数
2
解决办法
730
查看次数