如何让 C++ 推断我的模板类型名参数?

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)

Pat*_*rts 6

这是删除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)

在 godbolt.org 上尝试一下

在 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)

在 godbolt.org 上尝试一下