小编use*_*569的帖子

模板替换和SFINAE中的私有成员访问

class A { int a; };

template<typename, typename = void>
class test {};

template<typename T>
class test<T,decltype(T::a)> {};

int main() { test<A> a; }
Run Code Online (Sandbox Code Playgroud)

上面的代码编译时没有错误clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final),但无法编译g++-5 (Ubuntu 5.4.1-2ubuntu1~16.04) 5.4.1 20160904g++-6 (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901出现如下错误:

main.cpp: In function ‘int main()’:
main.cpp:9:22: error: ‘int A::a’ is private within this context
 int main() { test<A> a; }
                      ^
main.cpp:1:15: note: declared private here
 class A { int a; };
Run Code Online (Sandbox Code Playgroud)

在我编译的两种情况下-std=c++11,但效果-std=c++14-std=c++1z …

c++ gcc templates clang sfinae

17
推荐指数
1
解决办法
564
查看次数

在非类型模板参数中评估constexpr lambda

Lambda表达式在未评估的上下文中是不允许的(例如在decltype中),并且直到最近才能成为常量表达式.因此,无法在模板参数中使用它们.

然而,在C++ 17中,常量表达式lambdas是可能的.这仍然不允许在模板参数中使用它们.

但是,特别是对于非类型模板参数,常量表达式lambda表达式可以在计算上下文中使用,例如:

template<int N> struct S { constexpr static int value = N; };

int main() {
    int N = S<[]()constexpr{return 42;}()>::value;
}
Run Code Online (Sandbox Code Playgroud)

但这仍然不起作用,因为在模板参数中明确禁止lambda表达式,无论是类型还是非类型.

我的问题是不允许上述结构的原因.我可以理解函数签名中的lambda类型可能有问题,但这里闭包类型本身是无关紧要的,只使用(编译时常量)返回值.

我怀疑原因是lambda体中的所有语句都将成为模板参数表达式的一部分,因此如果体内的任何语句在替换期间格式不正确,则需要应用SFINAE.可能需要编译器开发人员的大量工作.

但这实际上是我的动力.如果可以使用上面的构造,那么SFINAE不仅可以用于常量表达式,还可以用于constexpr函数中有效的其他语句(例如文字类型声明).

除了对编译器编写者的影响之外,这是否会引起任何问题,例如标准中的含糊不清,矛盾或复杂性?

c++ lambda templates sfinae c++17

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

标签 统计

c++ ×2

sfinae ×2

templates ×2

c++17 ×1

clang ×1

gcc ×1

lambda ×1