std::pair<auto, auto> return 类型
std::pair<auto, auto> return type
我在 std::pair
里玩 auto
。在下面的代码中,函数 f
应该 return 类型的 std::pair
取决于模板参数。
一个工作示例:
示例 1
template <unsigned S>
auto f()
{
if constexpr (S == 1)
return std::pair{1, 2}; // pair of ints
else if constexpr (S == 2)
return std::pair{1.0, 2.0}; // pair of doubles
else
return std::pair{0.0f, 0.0f}; // pair of floats
}
这适用于 gcc 9.2、gcc 10.0、clang 9.0 和 clang 10.0。
接下来,为了清楚起见,我想将 return 类型显式写为 std::pair
:
示例 2
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return {1, 2};
/* ... */
}
gcc 9.2/10.0 和 clang 9.0/10.0 都编译失败。
gcc 9.2
error: invalid use of 'auto'
error: template argument 1 is invalid // first argument (auto) of std::pair
error: template argument 2 is invalid // second argument (auto) of std::pair
error: cannot convert '<brace-enclosed initializer list>' to 'int' in return
从上一条错误消息来看,gcc 9.2 似乎认为 std::pair<auto, auto>
是一个 int
。这怎么解释?
gcc 10.0
error: returning initializer list
这个错误是可以理解的,但是,我希望 std::pair
的构造函数被调用,或者我在这里遗漏了什么?
clang 9.0 和 10.0
'auto' not allowed in template argument
excess elements in scalar initializer
no matching function for call to 'f'
好吧,clang 不喜欢这些。从第二条错误消息来看,clang 似乎也认为 return 类型是 int
.
最后,为了修复使用 gcc 10.0 编译时出现的错误,我决定 return 显式 std::pair
:
示例 3
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return std::pair{1, 2};
/* ... */
}
clang 9.0 和 10.0
与以前相同,但增加了:
no viable conversion from returned value of type 'std::pair<int, int>' to function return type 'int'
这里 clang 仍然认为我们在 returning 一个 int
?
gcc 9.2
和以前一样。
gcc 10.0
有效!
我猜有些功能还得实现,或者在上面描述的一种情况下,编译器是对的还是错的?在我看来,示例 2 应该可行。还是不应该?
语法:
std::pair<auto, auto> f() { return std::pair(1, 2); }
~~~~~~~~~~~~~~~~~~~~~
是原始 Concepts TS 的一部分,但未包含在作为 C++20 一部分的 Concepts 提案中。因此,C++20 中唯一的占位符类型是 auto
(及其变体,如 auto**
)、decltype(auto)
和受限占位符(Concept auto
及其变体)。这种嵌套占位符类型非常有用,但不是 C++20 的一部分,因此函数声明格式不正确。
现在,gcc 允许它,因为 gcc 实现了 Concepts TS,我猜他们决定保留这个特性。 clang 从未实现过 TS,所以它没有。
无论如何,这:
std::pair<auto, auto> f() { return {1, 2}; }
永远是病式的。语法的意思是我们推导出return类型,然后要求它匹配pair<T, U>
一些类型T
和U
。我们基本上是在尝试调用发明的函数:
template <typename T, typename U>
void __f(std::pair<T, U>);
__f({1, 2}); // this must succeed
但是您无法从 {1, 2}
中推断出类型 - braced-init-list 没有类型。也许这是应该探索的东西(因为它很容易理解,至少在像这样的简单案例中),但它从来没有被允许。所以无论哪种方式拒绝它都是正确的。
最后:
gcc 9.2 seems to believe that std::pair<auto, auto>
is an int
. How can this be explained?
出于某种原因(可能是由于我们的 C 遗留隐式 int
),当 gcc 无法识别或理解类型时,它只是使用 int
作为错误消息中的占位符。这非常令人困惑,因为显然是 gcc 提出了 int
而不是源代码。但事情就是这样。
我在 std::pair
里玩 auto
。在下面的代码中,函数 f
应该 return 类型的 std::pair
取决于模板参数。
一个工作示例:
示例 1
template <unsigned S>
auto f()
{
if constexpr (S == 1)
return std::pair{1, 2}; // pair of ints
else if constexpr (S == 2)
return std::pair{1.0, 2.0}; // pair of doubles
else
return std::pair{0.0f, 0.0f}; // pair of floats
}
这适用于 gcc 9.2、gcc 10.0、clang 9.0 和 clang 10.0。
接下来,为了清楚起见,我想将 return 类型显式写为 std::pair
:
示例 2
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return {1, 2};
/* ... */
}
gcc 9.2/10.0 和 clang 9.0/10.0 都编译失败。
gcc 9.2
error: invalid use of 'auto'
error: template argument 1 is invalid // first argument (auto) of std::pair
error: template argument 2 is invalid // second argument (auto) of std::pair
error: cannot convert '<brace-enclosed initializer list>' to 'int' in return
从上一条错误消息来看,gcc 9.2 似乎认为 std::pair<auto, auto>
是一个 int
。这怎么解释?
gcc 10.0
error: returning initializer list
这个错误是可以理解的,但是,我希望 std::pair
的构造函数被调用,或者我在这里遗漏了什么?
clang 9.0 和 10.0
'auto' not allowed in template argument
excess elements in scalar initializer
no matching function for call to 'f'
好吧,clang 不喜欢这些。从第二条错误消息来看,clang 似乎也认为 return 类型是 int
.
最后,为了修复使用 gcc 10.0 编译时出现的错误,我决定 return 显式 std::pair
:
示例 3
template <unsigned S>
std::pair<auto, auto> f()
{
if constexpr (S == 1)
return std::pair{1, 2};
/* ... */
}
clang 9.0 和 10.0
与以前相同,但增加了:
no viable conversion from returned value of type 'std::pair<int, int>' to function return type 'int'
这里 clang 仍然认为我们在 returning 一个 int
?
gcc 9.2
和以前一样。
gcc 10.0
有效!
我猜有些功能还得实现,或者在上面描述的一种情况下,编译器是对的还是错的?在我看来,示例 2 应该可行。还是不应该?
语法:
std::pair<auto, auto> f() { return std::pair(1, 2); }
~~~~~~~~~~~~~~~~~~~~~
是原始 Concepts TS 的一部分,但未包含在作为 C++20 一部分的 Concepts 提案中。因此,C++20 中唯一的占位符类型是 auto
(及其变体,如 auto**
)、decltype(auto)
和受限占位符(Concept auto
及其变体)。这种嵌套占位符类型非常有用,但不是 C++20 的一部分,因此函数声明格式不正确。
现在,gcc 允许它,因为 gcc 实现了 Concepts TS,我猜他们决定保留这个特性。 clang 从未实现过 TS,所以它没有。
无论如何,这:
std::pair<auto, auto> f() { return {1, 2}; }
永远是病式的。语法的意思是我们推导出return类型,然后要求它匹配pair<T, U>
一些类型T
和U
。我们基本上是在尝试调用发明的函数:
template <typename T, typename U>
void __f(std::pair<T, U>);
__f({1, 2}); // this must succeed
但是您无法从 {1, 2}
中推断出类型 - braced-init-list 没有类型。也许这是应该探索的东西(因为它很容易理解,至少在像这样的简单案例中),但它从来没有被允许。所以无论哪种方式拒绝它都是正确的。
最后:
gcc 9.2 seems to believe that
std::pair<auto, auto>
is anint
. How can this be explained?
出于某种原因(可能是由于我们的 C 遗留隐式 int
),当 gcc 无法识别或理解类型时,它只是使用 int
作为错误消息中的占位符。这非常令人困惑,因为显然是 gcc 提出了 int
而不是源代码。但事情就是这样。