以下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;
}
这里的具体问题是你的函数模板和 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。lambdaint也隐式推导,但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比开始编写普通的函数模板声明要长。