为什么自由函数可以工作,但 lambda 中的等效函数却无法编译?

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

以下

get
函数将使用可变参数返回一个字符串数组。它还通过简单地转换整数来处理提供整数的情况。 我提供了这个转换函数的两个版本,一个是 lambda,另一个是自由函数。

有人可以解释一下为什么使用 lambda 无法编译,而看似相同的自由函数却可以正常工作。需要进行哪些更改才能使 lambda 案例正常工作?

#include <iostream>
#include <string>
#include <vector>
#include <ranges>
#include <format>
#include <array>
#include <type_traits>

// free function converter
template <typename KEY>
auto convert_to_string_view(const KEY& key)
{
    if constexpr (std::is_integral_v<KEY> && !std::is_same_v<KEY, bool>)
        return std::to_string(key);
    else
        return key;
}

// make an array out of varargs
template <typename T, typename... Args>
inline std::array<std::common_type_t<Args...>, sizeof...(Args)>
 make_array_from_vars(const Args&... args)
    requires (std::is_constructible_v<std::common_type_t<Args...>, Args> && ...)
{
    return { args... };
}



template<typename... KEYS>
auto get(KEYS... keys) {

    // lambda 
    auto convert_to_sv = [](const auto& key){
            if constexpr (std::is_integral_v<decltype(key)> && !std::is_same_v<decltype(key), bool>) {
                return std::to_string(key); 
            }
            else {
                return key;
            }
        };
    return make_array_from_vars<std::string_view>(convert_to_string_view(keys)...);
// using the lambda
    //return make_array_from_vars<std::string_view>(convert_to_sv(keys)...); FAILS

}

int main() {
    auto d = std::string("blablabla");
    auto tuple_range = get(d.append("!asdsads"), "blas", 0, 0);
    std::cout << tuple_range[0] << std::endl;
    return 0;
}
c++ lambda c++23
1个回答
1
投票

这里的具体问题是你的函数模板和 lambda 正在检查不同的东西:

template <typename KEY>
auto convert_to_string_view(const KEY& key)
{
    if constexpr (std::is_integral_v<KEY> && !std::is_same_v<KEY, bool>)

auto convert_to_sv = [](const auto& key){
    if constexpr (std::is_integral_v<decltype(key)> && !std::is_same_v<decltype(key), bool>) {

函数模板正在检查类型参数

KEY
是否是整型而不是
bool
。 lambda 对
decltype(key)
进行相同的检查。

现在,考虑用

int
来称呼两者。函数模板推导
KEY=int
并检查
int
。 lambda 也隐式推导
int
,但
decltype(key)
不是
int
- 它是
int const&
,因为那是变量的类型。事实上,
integral_v<decltype(key)>
永远不会正确的——因为引用不是不可或缺的。

为了让它们对齐,你可以引入一个模板参数,然后做同样的检查:

auto convert_to_sv = []<class K>(K const& key){
    if constexpr (std::is_integral_v<K> && !std::is_same_v<K, bool>) {

这现在具有相同的含义。


一般来说,缩写函数模板语法仅在您确实不需要变量的类型时才有用。一旦您开始需要它 - 使用

decltype
获取它现在比开始编写普通函数模板声明要长。

© www.soinside.com 2019 - 2024. All rights reserved.