我在玩弄std::pair
中的auto
。在下面的代码中,函数f
应该返回一个取决于模板参数的类型的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上工作。
接下来,出于清晰的原因,我想明确地将返回类型写为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似乎也认为返回类型是int
。
最后,为了修复使用gcc 10.0编译时获取的错误,我决定明确返回一个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仍然认为我们正在返回一个int
?
gcc 9.2
与之前相同。
gcc 10.0
可以了!
我猜还有一些功能需要实现,或者在上述某种情况中,是否存在一个编译器是正确的,而另一个则错误?在我看来,样例2应该能够工作。或者不应该?
auto x = {1, 2};
可以工作,但前提是所有类型都相同。 - Barrystd::optional f() { return 4; }
能够工作。 - Barry