考虑以下案例:我有
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构建,我不能在最近的将来改变它.
考虑以下最小示例:
#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)
我对 a、b 和 c 没有任何疑问,一切都很清楚
但我不明白为什么 d 有效
d 中这对额外的大括号代表什么?我查了 C++20 标准,但我找不到答案。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 会使这两者都出错?
复制很简单:
#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) 基本思想是这样的:我有一些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
编译时的查找是错误的,并且编译器将产生一个漂亮的错误。
但我注意到奇怪的行为:
这个想法合法吗?这段代码对于我想要实现的目标是否正确?哪个编译器在这里告诉我真相?
如果不是,正确的方法是什么?
任何到 C++ 标准的链接都值得赞赏。我通读了 constexpr 相关的章节,但我有疑问。
有简单的代码,其中 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++ 函数模板重载解析示例(从实际代码中最小化)
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)
我相信在这两种情况下,专业化都会赢得重载,因为专业化完全匹配,并且通过偏序 [temp.deduct.partial] 比主模板更专业
但是这个例子中的 clang 11 和 gcc 10.2 都同意在第二种情况下主模板获胜。这是两个编译器中的错误还是(可能)我对 C++ 标准不了解?
我不确定我对这些说明的解释:
virtual int getRadioChannel(RadioRef r) const = 0;
virtual int getNumChannels() = 0;
Run Code Online (Sandbox Code Playgroud)
对我来说,第一个意味着函数getRadioChannel的调用总是返回0而第二个函数在调用函数getNumChannels时什么都不做.我对吗 ?
提前致谢.