C++从成员类型中扣除类型的功能模板?

C++ funtion template deduction of type from member type?

本文关键字:类型 功能 成员 成员类 C++      更新时间:2023-10-16

我正在尝试编写一个C++函数模板,当使用类成员别名的参数调用该模板时,该函数可以推断出该别名的类。 一个简化版本会很好:

class A {
public :
using x_t = float;
void whatami() {printf("An");}
};
class B {
public :
using x_t = int;
void whatami() {printf("Bn");}
};
template<typename T>
void fn(T::x_t x) {
T t;
t.whatami();
};
...
A::x_t a;
fn(a);
...

g++ 7.3 错误是:

play$ g++ --std=c++11 x.cpp
x.cpp:19:12: error: variable or field ‘fn’ declared void
void fn(T::x_t x) {
^~~
x.cpp:19:16: error: expected ‘)’ before ‘x’
void fn(T::x_t x) {
^
x.cpp: In function ‘int main(int, char**)’:
x.cpp:29:3: error: ‘fn’ was not declared in this scope
fn(a);
^~

我把这解释为C++不能像fn(T::x_t x)那样推断出T,但我不确定。

思潮?

它不能从float推断出T,这就是a。在尝试填充模板时,它不会对 typedef 进行任何特殊考虑。它也不会在整个类型空间中搜索具有该名称成员的任何类型。

获得该推论的一种方法是通过引用拥有类来提升该成员类型,并将隐式转换添加回基元:

template <typename TOwner, typename TData>
class x_t {
TData data;
public:
constexpr x_t() = default;
constexpr x_t(TData data) : data(data) { }
constexpr operator TData() const { return data; }
};
struct A {
using x_t = x_t<A, float>;
/*...*/
};

然后部分专用化将正常工作:

template<typename TOwner, typename TData>
void fn(x_t<TOwner, TData> x) {
TOwner t;
t.whatami();
};

您可以在任何类型安全函数中使用实例

A::x_t a(42.0);
std::cout << a; // 42.0

(可悲的是,printf不算类型安全。 在这里使用流,来自优秀 FMT 库fmt::printf也可以(。

它可能无法达到您从成员那里轻松推断的目标,但这是一种可能性。

下面的函数应该采用对象(T(,因为你想要调用它的成员函数。

template<typename T>
void fn(T& x) 
{
x.whatami();
};

对模板函数的调用可以按如下方式完成:

A a;
fn(a);

它将结果打印为 => A 这是你想要的,对吧?

从任意模板 id 推导就像求解任意方程,这远远超出了编译器的能力。想一想:

template <int N>
using S = std::integral_constant<int, /* a super complex radical involving 42nd powers and 84th roots */>;
template <int N>
constexpr int solve(S<N>)
{
return N;
}

你认为编译器可以solve(std::integral_constant<int, 420>{});吗?不。

在您的情况下,模板 id 仅限于有限数量的情况,因此帮助编译器的一种简单的非侵入性方法是自己求解方程:

template <typename x_t>
using solve = std::conditional_t<
std::is_same_v<x_t, float>, A,
std::conditional_t<
// similar code for B
>
>;