dsm*_*ith 3 c++ templates type-inference
我想编写一个类型别名模板,它解析为大多数类型的模板参数的 const,如下所示:
template <typename T>
using TypeAlias = const T;
Run Code Online (Sandbox Code Playgroud)
但对于特定类型,例如 int,它只是解析为 T。
我尝试使用 std::conditional 以及包含类型别名的结构的专门化来执行此操作,但在所有情况下,编译器都无法推断类型。我的问题是:在下面的示例中我做错了什么?以及如何正确地做到这一点?
编辑:我正在一个非常大的代码库中工作,该代码库处理大量类型,并在 TypeAlias 的定义中向所有类型添加 const (这实际上是一个更复杂的类型,基本上是一个通过 const T 模板化的容器)。我正在尝试修改此代码库以接受不能为 const 的新类型,同时进行最少的修改。在所有模板化函数(如 foo)中显式指定类型并不是一个可行的解决方案。我真正正在寻找的是一种修改 TypeAlias 的方法,几乎没有其他任何东西。
示例1:
#include <stdio.h>
#include <type_traits>
template <typename T>
using TypeAlias = typename std::conditional<std::is_same<int, T>::value,
T, typename std::add_const<T>::type>::type;
template <typename T>
void foo(TypeAlias<T> var) {
printf("var = %f\n", static_cast<double>(var));
}
int main(int argc, char *argv[]) {
const int a = 1;
const float b = 2;
const double c = 3;
foo(a);
foo(b);
foo(c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
示例2:
template <typename T>
struct TypeHolder {
using type = const T;
};
template <>
struct TypeHolder<int> {
using type = int;
};
template <typename T>
void foo(typename TypeHolder<T>::type var) {
printf("var = %f\n", static_cast<double>(var));
}
int main(int argc, char *argv[]) {
int a = 1;
const float b = 2;
const double c = 3;
foo(a);
foo(b);
foo(c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是删除const特定类型集的另一种方法,只需添加一个重载并使用 SFINAE 根据推导的类型是否在该集中进行约束:
#include <iostream>
#include <type_traits>
template <class T, class... Ts>
inline constexpr bool is_any_v = (... || std::is_same_v<T, Ts>);
template <class T>
inline constexpr bool int_or_short_v = is_any_v<T, int, short>;
template <class T>
std::enable_if_t<!int_or_short_v<T>> foo(const T) { std::cout << "const" << std::endl; }
template <class T>
std::enable_if_t<int_or_short_v<T>> foo(T) { std::cout << "non-const" << std::endl; }
int main() {
const int a = 1;
const short b = 2;
const float c = 3;
const double d = 4;
foo(a);
foo(b);
foo(c);
foo(d);
}
Run Code Online (Sandbox Code Playgroud)
在 C++20 中,甚至更简单:
#include <iostream>
#include <concepts>
template <class T, class... Ts>
concept any_of = (... || std::same_as<T, Ts>);
void foo(const auto) { std::cout << "const" << std::endl; }
void foo(any_of<int, short> auto) { std::cout << "non-const" << std::endl; }
int main() {
const int a = 1;
const short b = 2;
const float c = 3;
const double d = 4;
foo(a);
foo(b);
foo(c);
foo(d);
}
Run Code Online (Sandbox Code Playgroud)