tl::expected 的 C++ 推导指南不使用 clang 编译,而是使用 gcc 编译(奇怪的错误消息)

问题描述 投票:0回答:1

我正在使用 tl::expected 并希望定义一个推导指南来创建我在 .cpp 文件中使用的特定类型的 tl::unexpected: (非常简单的例子)

class MyError {
public:
        enum ErrorType : int {
            none,
            type1,
            type2
        };

        MyError (ErrorType type, const std::string& description)
        {

        }
};

template<typename T>
tl::unexpected (MyError::ErrorType, const T&)->tl::unexpected<MyError>;

这段代码可以用 GCC 完美编译(尝试过 11 到 14 版本) 但无法使用 Clang 14 到 18 进行编译。此外,Clang 会给出奇怪的错误消息(就像语法完全损坏一样):

<source>:2476:35: error: expected ')'
 2476 | tl::unexpected (MyError::ErrorType, const T&)->tl::unexpected<MyError>;
      |                                   ^
<source>:2476:16: note: to match this '('
 2476 | tl::unexpected (MyError::ErrorType, const T&)->tl::unexpected<MyError>;
      |                ^
<source>:2476:16: error: cannot use parentheses when declaring variable with deduced class template specialization type
 2476 | tl::unexpected (MyError::ErrorType, const T&)->tl::unexpected<MyError>;
      |                ^
<source>:2476:26: error: declaration of variable 'ErrorType' with deduced type 'tl::unexpected' requires an initializer
 2476 | tl::unexpected (MyError::ErrorType, const T&)->tl::unexpected<MyError>;
      |                          ^
<source>:2476:46: error: expected ';' at end of declaration
 2476 | tl::unexpected (MyError::ErrorType, const T&)->tl::unexpected<MyError>;
      |                                              ^
      |                                              ;
<source>:2476:46: error: cannot use arrow operator on a type
5 errors generated.
Compiler returned: 1

推导指南中将MyError::ErrorType替换为int后:

template<typename T>
tl::unexpected (int, const T&)->tl::unexpected<MyError>;

错误消息(几乎)完全不同:

<source>:2476:17: error: expected unqualified-id
 2476 | tl::unexpected (int, const T&)->tl::unexpected<MyError>;
      |                 ^
<source>:2476:17: error: expected ')'
<source>:2476:16: note: to match this '('
 2476 | tl::unexpected (int, const T&)->tl::unexpected<MyError>;
      |                ^
2 errors generated.
Compiler returned: 1

但是,一个简单的模板示例在 Clang 中编译时没有错误:

template<typename T1, typename T2>
class C 
{
    private:
    T1 a;
    T2 b;
};

template<typename T>
C (int, const T&)->C<int, const T&>;

所以我不知道问题出在哪里?在我的推导指南中,在 tl::expected 实现中或在 clang 中(因为代码在由 GCC 编译时编译并运行得很好)

这里是上面示例的编译器资源管理器链接: https://godbolt.org/z/z3Ybrx1he

示例代码位于最后(第 2450 行及以下),位于 tl::预期标头内容之后。看起来 clang 和 gcc 都不知道 std::expected,因此我使用 tl::expected。

c++ templates clang++ deduction-guide
1个回答
0
投票

正如[temp.deduct.guide]/3中的标准所述:

演绎指南应位于相应类模板所属的范围内,并且对于成员类模板,具有相同的访问权限。

因此,将用户定义的推导指南放在命名空间范围中可以在 both clang 和 gcc 中工作。但请注意 [namespace.std]/4.4:

如果 C++ 程序声明以下内容,则其行为是未定义的:

  • 任何标准库类模板的推导指南。

我认为我们应该以同样的方式对待其他人的类模板。定义一种包装器并使用它似乎要好得多:

template<typename T>
tl::unexpected<MyError> MyError::as_unexpected(ErrorType, const T&);
© www.soinside.com 2019 - 2024. All rights reserved.