繁体   English   中英

在编译时延迟选择类型

[英]deferred selection of types during compile-time

当类型取决于函数中稍后可用的编译时信息时,我是否有一种标准方法可以在 c++20 的编译时选择类型,即由于中间编译时依赖关系,类型被“延迟”。

例如像这样的东西,它依赖于auto关键字但不编译:

template<bool value, typename ...>
struct bool_type : std::integral_constant<bool , value> {};

template<typename T>
void function(T* v) {
    auto r;
    bool different_type = false;
    if constexpr (...)
        r = (T)subfunc_a(v);
    else if constexpr (...)
        r = (T)subfunc_b(v);
    else if constexpr (...)
        r = (T)subfunc_c(v);
    else if constexpr (...);
        r = (T)subfunc_d(v);
    else if constexpr (...)
        r = (T)subfunc_e(v);
    // This condition depends on previous conditions. Extracting the condition
    // to the top of this function for use with `std::conditional` would be
    // burdensome. Decoupling the conditional in this way also risks errors. I
    // want to depend on the type system to enforce code correctness.
    else if constexpr (...) {
        r = (long)subfunc_f(v);
        different_type = true;
    }
    else if constexpr (...) {
        r = (unsigned long)subfunc_g(v);
        different_type = true;
    }
    else {
        static_assert(bool_type<false, T>::value, "Unsupported type");
    }
    do_common_work();
    if (different_type)
        do_more_work();
    *v = r;
}

或者这个例子依赖于static if提议,它阻止if constexpr条件创建新范围。 该提案未通过,因此代码无法编译。

template<typename T>
void function(T* v) {
    bool different_type = false;
    if constexpr (...)
        T r = subfunc_a(v);
    else if constexpr (...)
        T r = subfunc_b(v);
    else if constexpr (...)
        T r = subfunc_c(v);
    else if constexpr (...);
        T r = subfunc_d(v);
    else if constexpr (...)
        T r = subfunc_e(v);
    else if constexpr (...) {
        different_type = true;
        long r = subfunc_f(v);
    }
    else if constexpr (...) {
        different_type = true;
        unsigned long r = subfunc_g(v);
    }
    else {
        static_assert(bool_type<false, T>::value, "Unsupported type");
    }
    do_common_work();
    if (different_type)
        do_more_work();
    *v = r;
}

auto变量只能从 C++ 中的初始化表达式推断其类型。 如果您不想显式指定其类型,则可以将初始化提取到一个单独的函数中,该函数return s 必要的值(类型为auto )并使用此函数的调用进行初始化。

特别是,提取的函数可以是 lambda 表达式,因此您会得到一个立即调用的函数表达式或 IIFE:

#include <iostream>
#include <type_traits>

template <bool value, typename...>
struct bool_type : std::integral_constant<bool, value> {};

template <typename T> void function(T *v) {
    bool different_type = false;
    auto r = [&] {  // create a function
        if constexpr (std::is_same_v<T, int>) {
            return 10;
        } else if constexpr (std::is_same_v<T, double>) {
            return 10.0;
        } else if constexpr (std::is_same_v<T, long>) {
            different_type = true;
            return 10LL;
        } else {
            static_assert(bool_type<false, T>::value, "Unsupported type");
        }
    }();  // immediately invoke the created function
    std::cout << typeid(r).name() << " " << different_type << "\n";
    *v = r;
}

int main() {
    int a;
    double b;
    long c;
    [[maybe_unused]] float d;
    function(&a); // int 0
    function(&b); // double 0
    function(&c); // long long 1
    // function(&d);  // compilation error
}

在上面的代码中,lambda 表达式的返回类型为auto ,即它是从if constexpr选择的return值中自动推导出来的。 只选择了一个返回,所以返回类型是明确的,所以r的类型也被正确推断。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM