如何修复模板中的错误重构decltype [英] How to fix error refactoring decltype inside template

查看:323
本文介绍了如何修复模板中的错误重构decltype的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

修改可能无法完成,参见函数模板的函数指针的清理实现尽管答案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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆