是否需要在noexcept运算符中进行std :: decay?

问题描述

以下代码要求在 gcc 中的std::decay中使用noexcept operator,但不能在 clang 中使用。

template<typename... Ts>
class B;

template<typename T>
class B<T> {
    T t;
public:
    template<typename U>
    constexpr B(U&& t)
    // without decay - strange behavior in gcc,see main below  <===
    noexcept(noexcept(T{std::forward<U>(t)}))
        // if adding decay - all cases in main are ok with both gcc and clang
        // noexcept(noexcept(std::decay_t<T>{std::forward<U>(t)}))
    : t(std::forward<U>(t)) {}
};

template<typename T,typename... Ts>
class B<T,Ts...>: protected B<Ts...> {
public:
    template<typename U,typename... Us>
    constexpr B(U&& t,Us&&... ts)
        : B<Ts...>{std::forward<Us>(ts)...} {}
};

template<typename... Ts>
constexpr auto create(Ts&&... ts) {
    return B<Ts...>{std::forward<Ts>(ts)...};
}

template<typename... Ts>
B(Ts...) -> B<Ts...>;

主要

int main() {
    // ok in both gcc and clang:
    // [1] the "hello" parameter is not last
    auto b1 = create("hello",1); 
    auto b2 = create(1,"hello",5);
    // [2] passing it directly to the ctor of B
    B b3(1,"hello");

    // fails with gcc when the noexcept doesn't use decay
    // but only if "hello" is the last argument and passed via a function
    auto b4 = create(1,"hello");
    auto b5 = create("hello");
}

gcc的编译错误是:

<source>:13:40: error: invalid conversion from 'const char*' to 'char' 
         [-fpermissive]

   13 |     noexcept(noexcept(T{std::forward<U>(t)}))
      |                         ~~~~~~~~~~~~~~~^~~
      |                                        |
      |                                        const char*

代码https://godbolt.org/z/s7rf64

对这种奇怪行为有任何想法吗?这是gcc错误吗?还是确实需要std::decay

解决方法

在@Marek R的评论之后,这似乎是gcc中的错误。

A bug was opened on gcc

以下情况对于gcc而不是对clang也无效:

template<typename T,typename U>
auto convert(U&& t) {
    // fails on gcc:
    return T{std::forward<U>(t)};
    // works ok if it is not brace initialization:
    // return T(std::forward<U>(t));
}

template<std::size_t INDEX,typename T,typename U,typename... Us>
auto convert(U&& t,Us&&... ts) {
    if constexpr(INDEX == 0) {
        return convert<U>(t);
        // works well if we add decay
        // return convert<std::decay_t<U>>(t);
    }
    else {
        return convert<INDEX-1,T>(ts...);
    }
}

int main() {
    // fails with gcc
    auto p = convert<1,const char*>(1,"hello");
}

代码:https://godbolt.org/z/jqxbfj

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...