在编译时延迟选择类型
deferred selection of types during compile-time
有没有一种标准方法可以让我在 c++20 的编译时 select 一个类型,当该类型依赖于函数后面可用的编译时信息时,即该类型是“延迟的” " 因为中间编译时依赖性。
例如像这样依赖于 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 表达式,所以你得到 an immediately invoked function expression 或 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 表达式的 return 类型为 auto
,即它是根据 if constexpr
选择的 return
自动推导出来的。只选择了一个 return,所以 return 类型是明确的,所以 r
的类型也被正确推断。
有没有一种标准方法可以让我在 c++20 的编译时 select 一个类型,当该类型依赖于函数后面可用的编译时信息时,即该类型是“延迟的” " 因为中间编译时依赖性。
例如像这样依赖于 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 表达式,所以你得到 an immediately invoked function expression 或 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 表达式的 return 类型为 auto
,即它是根据 if constexpr
选择的 return
自动推导出来的。只选择了一个 return,所以 return 类型是明确的,所以 r
的类型也被正确推断。