如何修复模板中的错误重构decltype [英] How to fix error refactoring decltype inside template
问题描述
修改可能无法完成,参见函数模板的函数指针的清理实现尽管答案1有一个C宏解决方法 https://stackoverflow.com/a/18706623/2332068
我将一个函数传入一个成为构造函数预先提供的参数的模板,但也需要在该函数上使用 decltype
来将函数类型传递给 unique_ptr< ;. ..>
template instantiator(?是那个正确的单词)
如果我预先使用 decltype
作为一个额外的模板参数,但不是如果我在作为参数传递的函数模板内调用它。
我使用g ++ 4.9.2,并在这里扩展我的探索调用子类的unique_ptr继承模板的构造,我继承的unique_ptr
有我发现一些析构函数不会返回 void
,所以我想要一个更通用的模板,它不需要指定析构函数类型。
我现在的代码是:
pre $ void free_int(int * p){
删除p;
}
模板< typename T,void(* D)(T *)>
class unique_dptr:public std :: unique_ptr< T,decltype(D)> {
public:unique_dptr(T * t):std :: unique_ptr< T,decltype(D)>(t,D){};
};
使用int_ptr = unique_dptr< int,:: free_int>;
int_ptr i(new int(2));
但请注意 void(* D)(T *)
调用签名以将析构函数限制为一个void函数,该函数将指针指向 T
以这种形式使用的的unique_ptr
:
的unique_ptr< FOO,decltype( &安培; :: free_foo)GT;
我想要这样的东西:
模板< typename T,typename D>
class unique_gptr:public std :: unique_ptr< T,decltype(& D)> {
public:unique_gptr(T * t):std :: unique_ptr< T,decltype(& D)>(t,D){};
};
使用int_gptr = unique_gptr< int,:: free_int>;
int_gptr ig(new int(2));
但编译器讨厌它:
error:template argument 2 is invalid
class unique_gptr:public std :: unique_ptr< T,decltype(& D)> {
^
毫无疑问,古老的C-macro风格的标记粘贴是我错误的瞄准
我试着从 decltype(& D)中删除
但会导致错误: &
error:decltype的参数必须是表达式
然而,这是正常的:
模板<类型名称T,类型名称D,D F>
class unique_gptr:public std :: unique_ptr< T,D> {
public:unique_gptr(T * t):std :: unique_ptr< T,D>(t,F){};
};
使用int_gptr = unique_gptr< int,decltype(& :: free_int),:: free_int>;
int_gptr ig(new int(2));
但我想知道我做错了,我无法管理移动 decltype(& :: free_int)
。
其他解决方案< h1>
我意识到我可以为其他固定的自由函数类型编写额外的特化,替换 void(*)(void *)
我知道我可以覆盖我的类型的 std :: default_delete
。
但是这实际上是模板构成中的一个练习
我认为c ++
$ b
模板< typename T,typename D>
class unique_gptr:public std :: unique_ptr< T,decltype(& D)> {
public:unique_gptr(T * t):std :: unique_ptr< T,decltype(& D)>(t,D){};
};
使用int_gptr = unique_gptr< int,:: free_int>;
int_gptr ig(new int(2));
注意 decltype
应用于 D
,它被声明为 typename
。所以 D
是一种类型。但是 decltype
不能用在类型上。
首先,代码尝试得到一个类型的地址(&
)。其次, decltype
的参数预期为表达式,但不是类型或类型的地址。为了便于理解,我们可以说 decltype
预计它的参数是一个变量,如下例所示。
int main()
{
int i = 10;
decltype(i)j;
decltype(int)k; / *编译器错误。 * /
decltype(& int)l; / *编译器错误。 * /
返回0;
}
您还希望编译器替换 D
与
:: free_int
。和 :: free_int
被传递在作为非类型模板参数。但是 D
是一个类型模板参数。非类型模板参数以实际类型开始(例如 int
, struct a *
或类型模板名称) 。虽然类型模板参数以 typename
或 class
开头。非类型模板参数的一个简单示例
template< int INIT>
void func2(void)
{
decltype(INIT)j = INIT;
int main()
{
func2< 10>();
返回0;
当你传入像之类的函数指针时:: free_int
,您需要非类型模板参数,它必须以类型开头。而你希望函数指针的类型是可替换的。所以函数指针的类型必须是类型模板参数。这些使他们成为两个模板参数。
这就是在模板< typename T,typename D,D F>中需要三个模板参数的原因。 code>,这是你最好的结果。
edit Possibly can't be done, see Clean implementation of function template taking function pointer although answer 1 there has a C macro work-around https://stackoverflow.com/a/18706623/2332068
I'm passing a function into a template to become a pre-supplied argument to the constructor, but also need to use decltype
on that function to pass the function type to unique_ptr<...>
template instantiator(? is that the right word)
It works if I pre-use decltype
as an extra template argument, but not if I invoke it inside the template on the function passed as a parameter.
I'm using g++ 4.9.2, and extending my explorations here Calling inherited template constructor of unique_ptr subclass where I subclass unique_ptr
to have a fixed destructor, I find that some destructor functions do not return void
, so I want a more generic template that does not need to specify the destructor function type.
My current code is:
void free_int(int* p) {
delete p;
}
template<typename T, void (*D)(T*)>
class unique_dptr : public std::unique_ptr<T, decltype(D)> {
public: unique_dptr(T* t) : std::unique_ptr<T, decltype(D)>(t, D) { };
};
using int_ptr = unique_dptr<int, ::free_int>;
int_ptr i(new int(2));
but note the void (*D)(T*)
calling signature to restrict the destructor to a void function that takes a pointer to T
Given normal use of unique_ptr
in this form:
unique_ptr<foo, decltype(&::free_foo)>
I want to have something like this:
template<typename T, typename D>
class unique_gptr : public std::unique_ptr<T, decltype(&D)> {
public: unique_gptr(T* t) : std::unique_ptr<T, decltype(&D)>(t, D) { };
};
using int_gptr = unique_gptr<int, ::free_int>;
int_gptr ig(new int(2));
but the compiler hates it:
error: template argument 2 is invalid
class unique_gptr : public std::unique_ptr<T, decltype(&D)> {
^
No doubt ancient C-macro style token pasting is what I am wrongly aiming at.
I have tried removing the &
from decltype(&D)
but that leaves the error:
error: argument to decltype must be an expression
however this is OK:
template<typename T, typename D, D F>
class unique_gptr : public std::unique_ptr<T, D> {
public: unique_gptr(T* t) : std::unique_ptr<T, D>(t, F) { };
};
using int_gptr = unique_gptr<int, decltype(&::free_int), ::free_int>;
int_gptr ig(new int(2));
but I wonder what I am doing wrong that I can't manage move the decltype(&::free_int)
into the template.
Other solutions
I realise that I can just write additional specialisations for other fixed free-function types, replacing void(*)(void*)
I realise that I can override the std::default_delete
for my type.
But this is really an exercise in template composition
I think for c++11 it is impossible to achieve what you want.
template<typename T, typename D> class unique_gptr : public std::unique_ptr<T, decltype(&D)> { public: unique_gptr(T* t) : std::unique_ptr<T, decltype(&D)>(t, D) { }; }; using int_gptr = unique_gptr<int, ::free_int>; int_gptr ig(new int(2));
Notice that decltype
is applied on D
, which is declared as a typename
. So D
is a type. But decltype
can't be used on a type.
Firstly the code tries to get the address of a type (&
). Secondly, the argument of decltype
is expected to be an expression, but not a type or "the address of a type". To make it easier to understand, we can say that decltype
expects its argument to be a "variable", like the following example.
int main()
{
int i = 10;
decltype(i) j;
decltype(int) k; /* Compiler error. */
decltype(&int) l; /* Compiler error. */
return 0;
}
You also want the compiler to replace D
with ::free_int
. And ::free_int
is passed in as a non-type template argument. However D
is a type template parameter. A non-type template parameter starts with an actual type (e.g. int
, struct a*
or a type template name). While a type template parameter starts with typename
or class
. An easier example for non-type template parameter,
template<int INIT>
void func2(void)
{
decltype(INIT) j = INIT;
}
int main()
{
func2<10>();
return 0;
}
When you pass in a function pointer like ::free_int
, you need a non-type template parameter, which must be preceded by a type. And you want the type of the function pointer to be "replaceable". So the type of the function pointer has to be a type template parameter. These make them two template parameters.
That's the reason you need three template parameters in template<typename T, typename D, D F>
, which is the best result you have.
这篇关于如何修复模板中的错误重构decltype的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!