小编W.F*_*.F.的帖子

c ++ 17中的非类型模板参数可以是decltype(auto)吗?

我发现gcc和clang允许decltype(auto)在非类型模板参数类型子句中使用.例如:

template <decltype(auto)>
struct X {};

int foo ;

int main() {
    X<(foo)> x;
    static_cast<void>(x);
}
Run Code Online (Sandbox Code Playgroud)

[现场演示gcc] [现场演示铿锵]

它是标准兼容功能还是一些gnu扩展?

c++ templates language-lawyer c++17

40
推荐指数
1
解决办法
1151
查看次数

为什么在使用模板化方法的嵌套结构时不允许使用泛型lambda?

据我所知 - 泛型lambda被转换为具有模板化的局部范围结构的对象operator().这使得通用lambda非常强大且易于使用的工具.另一方面,可以创建嵌套到函数中的结构,但是当结构具有模板化成员时,例如:

#include <iostream>

int main() {
    struct inner {
    template <class T>
       void operator()(T &&i) { }
    };
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

或者自己模仿:

int main() {
    template <class T>
    struct inner {
       void operator()(T &&i) { }
    };
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器似乎有编译它的问题:

error: invalid declaration of member template in local class
Run Code Online (Sandbox Code Playgroud)

error: a template declaration cannot appear at block scope
Run Code Online (Sandbox Code Playgroud)

我认为问题在c ++标准中比在编译器bug中更多.lambdas被允许拥有模板化成员而不是本地结构的原因是什么?

我发现了这个问题,但我认为答案有点过时(即使对于c ++ 11,我也不认为这是真的).

c++ templates local-class generic-lambda c++14

32
推荐指数
1
解决办法
1214
查看次数

结构化绑定的decltype(auto)应该是引用吗?

考虑一个例子:

#include <iostream>
#include <type_traits>
#include <tuple>

int main() {
    auto tup = std::make_tuple(1, 2);
    auto [ a, b ] = tup;
    decltype(auto) e = a;
    std::cout << std::boolalpha << std::is_reference_v<decltype(e)> << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

在这个简单的例子中,clang(输出:)falsegcc(输出:)true不一致.记住,例如这个Q&As应该e是一个参考还是一个gcc bug?或者代码可能不正确?

c++ language-lawyer c++17 structured-bindings

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

为什么在这种情况下非类型模板参数不能自动?

我设法重现问题的最简单的片段如下:

#include <variant>

template <auto V>
using ic = std::integral_constant<decltype(V), V>;

enum { shake }; 
int milk(ic<shake>);

template <class...>
struct context {
    template <auto V>
    decltype(milk(ic<V>{})) get() {
        return std::get<decltype(milk(ic<V>{}))>(value);
    }
    std::variant<int> value;
};

int main(){
    context<int> c;
    c.get<shake>();
}
Run Code Online (Sandbox Code Playgroud)

[clang]中有一些可疑的东西,因为它表明:

prog.cc:13:42: error: a non-type template parameter cannot have type 'auto'
        return std::get<decltype(milk(ic<V>{}))>(value);
                                         ^
prog.cc:3:16: note: template parameter is declared here
template <auto V>
               ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

当我们更改ic为别名类型或使用未模板化的版本时,context所有内容都按预期工作.那真的是铿锵的错误还是我错过了一些明显的东西?

PS.在[gcc]中,一切都按预期工作......

c++ templates language-lawyer auto c++17

21
推荐指数
1
解决办法
366
查看次数

我能在模板参数中声明constexpr lambda吗?

我知道这就像打开潘多拉盒子一样,但它并没有停止打扰我.考虑一个简单的例子:

#include <type_traits>

template <auto>
struct Foo: std::false_type { };

template <>
struct Foo<[](){return 1;}()>:std::true_type { };

int main() {
    static_assert(Foo<1>::value);
}
Run Code Online (Sandbox Code Playgroud)

我知道lambdas不能在未评估的上下文中声明,但显然这不是这里的情况.什么是更奇怪的clang 5.0.0(我猜,首先部分支持constexpr lambda)确实编译它.

它是编译器错误还是C++ 17允许这样做?

c++ templates language-lawyer c++17

19
推荐指数
1
解决办法
1187
查看次数

无法使用来自私有基的公共成员函数的指针

考虑这段代码:

class Base {
 public:
  int foo(int x) const { return 2*x; }
};

class Derived : Base {
 public:
  using Base::foo;
};
Run Code Online (Sandbox Code Playgroud)

现在Derived有一个公共方法 foo 并且可以调用它

Derived d;
d.foo(2);   // compiles (as it should)
Run Code Online (Sandbox Code Playgroud)

但是,如果我通过指针使用该方法,我将无法执行任何操作:

Derived d;
(d.*&Derived::foo)(2);  // does not compile because `Derived::foo` expects a pointer to `Base` and `Derived` cannot be casted to its private base class (without a C-style cast).
Run Code Online (Sandbox Code Playgroud)

对于这种行为是否有任何合乎逻辑的解释,或者可能是标准中的疏忽?

c++ language-lawyer

19
推荐指数
1
解决办法
609
查看次数

可以在尾随返回类型语法中直接使用参数值(不是其类型而是值本身)

考虑最小的例子:

template <int>
struct bar { };

int main() 
{
    [](auto i) -> bar<i> { return {}; };
}
Run Code Online (Sandbox Code Playgroud)

甚至:

template <int>
struct bar {};

template <class I>
auto foo(I i) -> bar<i> {}
Run Code Online (Sandbox Code Playgroud)

clang编译两种形式没有问题,但gcc发现使用无效(例如1),(例如2)

这个问题可能看起来很愚蠢,但是参数的类型可以让constexpr转换运算符重载(在这种情况下,i从传递给lambda/foo的值推导出的类型int是以constexpr方式推导出来的),在这种情况下,不要强迫它做一些变通方法直接访问它...

c++ language-lawyer c++11 trailing-return-type

18
推荐指数
2
解决办法
820
查看次数

在模板模板参数的情况下,非类型模板参数的占位符类型是否可互换

考虑一个简单的例子:

int x;

template <template <auto> class TT>
struct Foo {
   void foo() {
      TT<(x)> tt;
      static_cast<void>(tt);
   }
};

template <decltype(auto)>
struct Bar { };


int main() {
    Foo<Bar> foobar;
    foobar.foo();
}
Run Code Online (Sandbox Code Playgroud)

[clang]似乎处理decltype(auto)占位符的想法,尽管auto在模板模板参数声明中使用没有问题.

[gcc]另一方面 - 不是很好:

prog.cc:6:13:错误:'x'的值在常量表达式中不可用


通常 - 根据标准预期哪种行为?或许一切皆有可能,而且代码格式不正确(这次我想不是,但不能明确地排除它)?

PS.很抱歉再次打破其中一个编译器;)

c++ templates language-lawyer c++17

18
推荐指数
1
解决办法
290
查看次数

有没有办法将模板化的函数签名作为模板模板参数传递

通过使用模板模板参数,可以将模板化的类传递给类,而无需在其参数上指定类型.我想知道有没有办法将函数的模板化签名传递给模板模板参数,以便能够专门考虑函数的哪个变体被认为是向前的.

要清楚 - 我知道我做不到:

template <class T>
void foo() { /*...*/ }

template <template <class...> class FooType>
struct Foo { /*...*/ };

int main() {
    Foo<decltype(foo)> f;
}
Run Code Online (Sandbox Code Playgroud)

但不知何故,我希望能够将模板的模板签名传递给Foo.它甚至可能吗?

c++ templates

17
推荐指数
2
解决办法
2418
查看次数

如何为嵌套模板类提供演绎指南?

根据[ temp.deduct.guide/3 ]:

(...)演绎指南应在与相应的类模板相同的范围内声明,对于成员类模板,具有相同的访问权限.(......)

但是下面的例子似乎没有在[gcc][clang]中编译.

#include <string>

template <class>
struct Foo {
    template <class T>
    struct Bar {
        Bar(T) { }
    };
    Bar(char const*) -> Bar<std::string>;
};

int main() {
    Foo<int>::Bar bar("abc");
    static_cast<void>(bar);
}
Run Code Online (Sandbox Code Playgroud)

嵌套模板类的演绎指南的正确语法是什么?或者这个可能是正确的但是编译器还没有支持它?


类似的语法但没有嵌套类在gcc和clang中编译都很好:

#include <string>

template <class T>
struct Bar {
    Bar(T) { }
};
Bar(char const*) -> Bar<std::string>;

int main() {
    Bar bar("abc");
    static_cast<void>(bar);
}
Run Code Online (Sandbox Code Playgroud)

c++ templates template-argument-deduction c++17

16
推荐指数
1
解决办法
537
查看次数