使用 decltype 的函数参数类型
Function parameter type using decltype
注:本题提供的示例不是生产代码,完全没有意义。它只是为了说明我的问题。
我在测试decltype
的可能性,特别是如果它用于推导函数参数类型,运行成问题:
假设有两个 类 结构如下:
struct ClassInt
{
// Note: no default ctor
ClassInt(int value)
: m_Value(value)
{}
int m_Value;
};
struct ClassDouble
{
// Note: no default ctor
ClassDouble(double value)
: m_Value(value)
{}
double m_Value;
};
现在,我编写了一个函数,它(以某种方式)通过字符串检索类型参数(应该是上述之一)的实例,并将给定值分配给它的 m_Value
成员:
template< typename Ty >
Ty* get_fake_ptr() { return nullptr; }
// Retrieve pointer to Ty object by name and assign its value member.
// The problem is that we don't actually have an instance of Ty at the point
// where we want to define the type of the parameter "value".
template< typename Ty >
void assign(std::string name, decltype(get_fake_ptr<Ty>()->m_Value) value)
{
// Somehow get pointer to a Ty object by name
Ty* obj = ????;
// Assign
obj->m_Value = value;
}
现在,参数 value
的类型取决于类型参数,因为使用的 类 成员 m_Value
的类型不同。如您所见,我使用 decltype
解决了它。现在,通常,您会在参数上使用 decltype
,如下所示:
template<typename Ty>
void assign(Ty& obj, decltype(obj.m_Value) value);
但这在这里显然是不可能的,因为实际实例是在函数体中检索的,因此在声明函数参数的地方不可用。
我通过使用模板函数 get_fake_ptr
将它组合在一起,它只是 returns 一个匹配类型的 nullptr
所以我有一个 "pseudo instance" 编译器可以用来确定成员类型。它有效:
现在,正如我所说,这对我来说真的很老套。所以:
有没有更好的方法解决这个问题?
谢谢!
我认为这种方法没有任何问题。
在模板元编程方面,这些 "hacks" 是课程的标准。
不过,我可以建议一种略有不同的设计模式。像这样:
struct ClassInt
{
// Note: no default ctor
ClassInt(int value)
: m_Value(value)
{}
typedef int m_value_t;
m_value_t m_Value;
};
struct ClassDouble
{
// Note: no default ctor
ClassDouble(double value)
: m_Value(value)
{}
typedef double m_value_t;
m_value_t m_Value;
};
// ...
template< typename Ty >
void assign(std::string name, typename Ty::value_t value)
{
// Somehow get pointer to a Ty object by name
Ty* obj = ????;
// Assign
obj->m_Value = value;
}
另一种选择是添加另一个模板参数,让赋值处理匹配类型和转换。任何不可转换的值类型都会产生编译错误。
template<typename Ty, typename VALUE_TYPE>
void assign(std::string name, VALUE_TYPE value) {
Ty* obj = ???
obj->m_Value = value;
}
您可以使用 decltype(std::declval<T>().m_Value)
来推断 T
的 m_Value
成员的类型,而不是使用您的 get_fake_ptr()
函数。他们最终实现了相似的目标。
顺便说一下,您的 get_fake_ptr()
函数不需要定义。您可以简单地将其保留为 template <typename T> T* get_fake_ptr();
,您仍然可以在 decltype
.
中使用它
注:本题提供的示例不是生产代码,完全没有意义。它只是为了说明我的问题。
我在测试decltype
的可能性,特别是如果它用于推导函数参数类型,运行成问题:
假设有两个 类 结构如下:
struct ClassInt
{
// Note: no default ctor
ClassInt(int value)
: m_Value(value)
{}
int m_Value;
};
struct ClassDouble
{
// Note: no default ctor
ClassDouble(double value)
: m_Value(value)
{}
double m_Value;
};
现在,我编写了一个函数,它(以某种方式)通过字符串检索类型参数(应该是上述之一)的实例,并将给定值分配给它的 m_Value
成员:
template< typename Ty >
Ty* get_fake_ptr() { return nullptr; }
// Retrieve pointer to Ty object by name and assign its value member.
// The problem is that we don't actually have an instance of Ty at the point
// where we want to define the type of the parameter "value".
template< typename Ty >
void assign(std::string name, decltype(get_fake_ptr<Ty>()->m_Value) value)
{
// Somehow get pointer to a Ty object by name
Ty* obj = ????;
// Assign
obj->m_Value = value;
}
现在,参数 value
的类型取决于类型参数,因为使用的 类 成员 m_Value
的类型不同。如您所见,我使用 decltype
解决了它。现在,通常,您会在参数上使用 decltype
,如下所示:
template<typename Ty>
void assign(Ty& obj, decltype(obj.m_Value) value);
但这在这里显然是不可能的,因为实际实例是在函数体中检索的,因此在声明函数参数的地方不可用。
我通过使用模板函数 get_fake_ptr
将它组合在一起,它只是 returns 一个匹配类型的 nullptr
所以我有一个 "pseudo instance" 编译器可以用来确定成员类型。它有效:
现在,正如我所说,这对我来说真的很老套。所以:
有没有更好的方法解决这个问题?
谢谢!
我认为这种方法没有任何问题。
在模板元编程方面,这些 "hacks" 是课程的标准。
不过,我可以建议一种略有不同的设计模式。像这样:
struct ClassInt
{
// Note: no default ctor
ClassInt(int value)
: m_Value(value)
{}
typedef int m_value_t;
m_value_t m_Value;
};
struct ClassDouble
{
// Note: no default ctor
ClassDouble(double value)
: m_Value(value)
{}
typedef double m_value_t;
m_value_t m_Value;
};
// ...
template< typename Ty >
void assign(std::string name, typename Ty::value_t value)
{
// Somehow get pointer to a Ty object by name
Ty* obj = ????;
// Assign
obj->m_Value = value;
}
另一种选择是添加另一个模板参数,让赋值处理匹配类型和转换。任何不可转换的值类型都会产生编译错误。
template<typename Ty, typename VALUE_TYPE>
void assign(std::string name, VALUE_TYPE value) {
Ty* obj = ???
obj->m_Value = value;
}
您可以使用 decltype(std::declval<T>().m_Value)
来推断 T
的 m_Value
成员的类型,而不是使用您的 get_fake_ptr()
函数。他们最终实现了相似的目标。
顺便说一下,您的 get_fake_ptr()
函数不需要定义。您可以简单地将其保留为 template <typename T> T* get_fake_ptr();
,您仍然可以在 decltype
.