小编Kon*_*rov的帖子

用通用函数指针参数化函数模板的简洁方法

考虑以下案例:我有

int bar1();
double bar2();
Run Code Online (Sandbox Code Playgroud)

我想要:

foo<bar1>(); // calls bar1, then uses its result.
foo<bar2>(); // calls bar2, then uses its result.
Run Code Online (Sandbox Code Playgroud)

天真的写模板方式foo()是使用附加参数:

template <typename T, T (*f)()> void foo () {
  // call f, do something with result
}
Run Code Online (Sandbox Code Playgroud)

这有效,但我需要做丑陋的语法:

foo<decltype(bar1()), bar1>(); // calls bar1, then uses its result
Run Code Online (Sandbox Code Playgroud)

我想写一些漂亮的东西,就像上面一样foo<bar1>.

PS请不要建议在运行时接受参数.我只需要使用函数指针进行编译时参数化.

PS抱歉忘记提及:我正在寻找C++ 14解决方案.C++ 17赞赏,我赞成使用C++ 17解决方案,但项目现在使用C++ 14构建,我不能在最近的将来改变它.

c++ templates decltype c++14

23
推荐指数
1
解决办法
1135
查看次数

初始化列表中的空大括号魔术

考虑以下最小示例:

#include <iostream>

struct X {
  X() { std::cout << "Default-ctor" << std::endl; }
  X(std::initializer_list<int> l) { 
      std::cout << "Ilist-ctor: " << l.size() << std::endl; 
  }
};

int main() {
    X a{};
    X b({}); // reads as construct from {}
    X c{{}}; // reads as construct from {0}
    X d{{{}}}; // reads as construct from what?
    // X e{{{{}}}}; // fails as expected
}
Run Code Online (Sandbox Code Playgroud)

Godbolt 示例

我对 a、b 和 c 没有任何疑问,一切都很清楚

但我不明白为什么 d 有效

d 中这对额外的大括号代表什么?我查了 C++20 标准,但我找不到答案。clang 和 gcc …

c++ initializer-list c++20

13
推荐指数
2
解决办法
1124
查看次数

const&amp;&amp; 绑定到 lambda 捕获中的 ref:clang 与 gcc?

在下面的代码中:

int foo() {
  int a = 5;
  auto l = [&r = std::move(std::as_const(a))] { return r; };
  return l();  
}
Run Code Online (Sandbox Code Playgroud)

clang 编译得很好

gcc 产生错误。

error: cannot capture 'std::move<const int&>((* & std::as_const<int>(a)))' by reference
Run Code Online (Sandbox Code Playgroud)

我需要社区的帮助来从 C++ 标准的角度争论这个案例:谁在 C++20 中是正确的以及为什么到底。

从 [expr.prim.lambda.capture] 我不清楚这个子句是否:

不带省略号的 init-capture 的行为就像它声明并显式捕获“auto init-capture”形式的变量一样

意味着 clang 是对的?如果是,那么为什么删除 as_const 会使这两者都出错?

godbolt 上的代码示例

c++ language-lawyer c++20

6
推荐指数
1
解决办法
114
查看次数

GCC vs普通lambda的铿锵:谁是正确的?

复制很简单:

#include <utility>

int foo (int&) { return 0; }
int bar (int&&) { return 0; }

int
main ()
{
  auto transparent = [](auto f, auto&& param) {
    return f(std::forward<decltype(param)>(param));
  };
  int a;
  transparent (foo, a);
  transparent (bar, std::move(a));
}
Run Code Online (Sandbox Code Playgroud)

clang编译好了,但是gcc说:

04a-repro.cc: In instantiation of 'main()::<lambda(auto:1, auto:2&&)> [with auto:1 = int (*)(int&); auto:2 = int]':
04a-repro.cc:9:45:   required by substitution of 'template<class auto:1, class auto:2> main()::<lambda(auto:1, auto:2&&)>::operator decltype (((main()::<lambda(auto:1, auto:2&&)>)0u).operator()(static_cast<auto:1>(<anonymous>), static_cast<auto:2&&>(<anonymous>))) (*)(auto:1, auto:2&&)() const [with auto:1 = int (*)(int&); auto:2 …
Run Code Online (Sandbox Code Playgroud)

c++ gcc clang c++14

5
推荐指数
0
解决办法
133
查看次数

扔进 constexpr 函数:我们需要包装条件吗?

基本思想是这样的:我有一些constexpr函数,我想用它throw来发出错误信号和延迟编译以避免正常流程中出现此错误:

template <size_t N>
auto constexpr find_elt(const std::array<int, N>& a, int k) {
  for (size_t i = 0; i < N; ++i)
    if (k == a[i])
      return i;
  throw "not found";
}
Run Code Online (Sandbox Code Playgroud)

进而:

constexpr int result = find_elt(arr, 4);
Run Code Online (Sandbox Code Playgroud)

通常,如果数组中存在 4,我将在编译时获取其索引。

如果没有,我就会陷入困境throw编译时的查找是错误的,并且编译器将产生一个漂亮的错误。

但我注意到奇怪的行为:

在最新的 clang 下,一切正常

在最新的gcc下,一切都失败了

这个想法合法吗?这段代码对于我想要实现的目标是否正确?哪个编译器在这里告诉我真相?

如果不是,正确的方法是什么?

任何到 C++ 标准的链接都值得赞赏。我通读了 constexpr 相关的章节,但我有疑问。

c++ constexpr c++17

5
推荐指数
1
解决办法
749
查看次数

如何关闭 clang 中的本地数组合并?

有简单的代码,其中 clang 和 gcc 的行为不同。

int t;
extern void abort (void);

int f(int t, const int *a)
{
 const int b[] = { 1, 2, 3};
 if (!t)
   return f(1, b);
 return b == a;
}

int main(void)
{
 if (f(0, 0))
   abort ();
 return 0;
}
Run Code Online (Sandbox Code Playgroud)

铛:

> clang -v
clang version 4.0.1 (tags/RELEASE_401/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
> clang test.c
> ./a.out
Aborted
Run Code Online (Sandbox Code Playgroud)

海湾合作委员会:

> gcc -v
Target: x86_64-suse-linux
Thread model: posix
gcc version 7.2.0 (GCC)
> …
Run Code Online (Sandbox Code Playgroud)

c gcc clang compiler-optimization

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

C++ 函数模板重载:空大括号 vs 显式 int

下面有一些非常基本的 C++ 函数模板重载解析示例(从实际代码中最小化)

struct S {
    S() {}
    S(int) {}
};

template <typename T = S>
void foo(T x) { std::cout << "S" << std::endl; }

template <>
void foo<S>(S x) { std::cout << "S spc" << std::endl; }

int main() {
    foo({});
    foo(0);
}
Run Code Online (Sandbox Code Playgroud)

这里我们有两种情况。在第一种情况下编译器应默认初始化某些东西(如 S)在第二种情况下将 int 转换为某些东西(如 S)

Godbolt 上的活生生的例子

我相信在这两种情况下,专业化都会赢得重载,因为专业化完全匹配,并且通过偏序 [temp.deduct.partial] 比主模板更专业

但是这个例子中的 clang 11 和 gcc 10.2 都同意在第二种情况下主模板获胜。这是两个编译器中的错误还是(可能)我对 C++ 标准不了解?

c++ c++20 function-templates-overloading

3
推荐指数
1
解决办法
61
查看次数

一个虚函数头后跟一个语句

我不确定我对这些说明的解释:

virtual int getRadioChannel(RadioRef r) const = 0;
virtual int getNumChannels() = 0;
Run Code Online (Sandbox Code Playgroud)

对我来说,第一个意味着函数getRadioChannel的调用总是返回0而第二个函数在调用函数getNumChannels时什么都不做.我对吗 ?

提前致谢.

c++

-1
推荐指数
1
解决办法
94
查看次数