如何修复模板内部重构decltype的错误
How to fix error refactoring decltype inside template
edit可能无法完成,请参阅函数模板采用函数指针的干净实现,尽管答案1有一个C宏可以解决https://stackoverflow.com/a/18706623/2332068
我将一个函数传递到模板中,以成为构造函数的预提供参数,但也需要在该函数上使用decltype
将函数类型传递给unique_ptr<...>
模板实例化器(?这个词对吗)
如果我预先使用decltype
作为额外的模板参数,但如果我在作为参数传递的函数的模板内部调用它,它就不会起作用。
我使用g++4.9.2,并在这里扩展了我的探索。调用unique_ptr子类的继承模板构造函数,其中我将unique_ptr
子类化为具有固定的析构函数,我发现一些析构函数不返回void
,所以我想要一个更通用的模板,不需要指定析构函数类型。
我当前的代码是:
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));
但请注意,void (*D)(T*)
调用签名将析构函数限制为一个void函数,该函数使用指向T
的指针
给定以下形式的unique_ptr
的正常使用:
unique_ptr<foo, decltype(&::free_foo)>
我想要这样的东西:
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));
但编译器讨厌它:
error: template argument 2 is invalid
class unique_gptr : public std::unique_ptr<T, decltype(&D)> {
^
毫无疑问,古老的C宏风格的标记粘贴是我错误的目标。
我已经尝试从decltype(&D)
中删除&
,但这留下了错误:
error: argument to decltype must be an expression
但是这是可以的:
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));
但我想知道我做错了什么,我无法将decltype(&::free_int)
移动到模板中。
其他解决方案
我意识到我可以为其他固定的自由函数类型编写额外的专业知识,取代void(*)(void*)
我意识到我可以为我的类型覆盖std::default_delete
。
但这实际上是模板组合
我认为对于c++11来说,实现您想要的是不可能的。
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));
请注意,decltype
应用于D
,后者被声明为typename
。所以D
是一种类型。但是decltype
不能用于类型。
首先,代码尝试获取一个类型(&
)的地址。其次,decltype
的自变量应该是表达式,而不是类型或"类型的地址"。为了更容易理解,我们可以说decltype
希望它的自变量是一个"变量",就像下面的例子一样。
int main()
{
int i = 10;
decltype(i) j;
decltype(int) k; /* Compiler error. */
decltype(&int) l; /* Compiler error. */
return 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>();
return 0;
}
当传入像::free_int
这样的函数指针时,需要一个非类型模板参数,该参数前面必须有一个类型。并且您希望函数指针的类型是"可替换的"。因此,函数指针的类型必须是类型模板参数。这使它们成为两个模板参数。
这就是template<typename T, typename D, D F>
中需要三个模板参数的原因,这是您获得的最佳结果。
不能将decltype
与类型一起使用,因为目标是获取变量的类型。但在decltype(&D)
中,D
是一种类型。
我宁愿传递一个模板函数:
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) { };
};
template <typename T, typename D>
unique_gptr<T, D F> make_unique_gptr(T pointer, D deleter)
{
return unique_gptr<T, D, deleter>(pointer);
}
auto ptr = make_unique(new int(2), ::free_int);
您可以使用一些宏魔术:
template<class T, class D, D d>
struct UniqueDeleter : public std::unique_ptr<T, D> {
UniqueDeleter(T* t) : std::unique_ptr<T, D>(t, d) { };
};
template<class R, class T>
T decl_unique_deleter_ptr(R (*d)(T*));
#define DECL_UNIQUE_DELETER1(f) UniqueDeleter<decltype(decl_unique_deleter_ptr(&f)), decltype(&f), &f>
#define DECL_UNIQUE_DELETER2(T, f) UniqueDeleter<T, decltype(&f), &f>
#define DECL_UNIQUE_DELETER_GET_MACRO(_1, _2, NAME, ...) NAME
#define DECL_UNIQUE_DELETER_EXPAND(x) x
#define decl_unique_deleter(...) DECL_UNIQUE_DELETER_EXPAND(DECL_UNIQUE_DELETER_GET_MACRO(
__VA_ARGS__, DECL_UNIQUE_DELETER2, DECL_UNIQUE_DELETER1, _)(__VA_ARGS__))
现在你可以这样使用它:
decl_unique_deleter(int, free_int) ig(new int(2));
或者使用using
和一些更神奇的东西:
using int_gptr = decl_unique_deleter(free_int); // If accepted pointer type matches.
int_gptr ig(new int(2));
我还可以推荐一种替代解决方案:
auto i = new int(2);
BOOST_SCOPE_EXIT_ALL(&) { delete i; };
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 代码在main()中运行,但在函数中出现错误
- 释放错误后堆使用
- (C++)分析树以计算返回错误值的简单算术表达式
- 使用具有默认参数的函数模板进行 decltype 会使结果混乱(一个有趣的问题或 gcc 的错误)
- C++ 带有 decltype 的 SFINAE:替换失败成为错误?
- 编译错误与迭代器取消引用的 decltype
- GCC 中的编译器错误,但在将 decltype 与具有尾随返回类型语法的模板化成员函数一起使用时没有 clang
- C++ 中的 decltype() 会导致编译错误
- 在 C++11 中使用 decltype() 时出错(在 gcc 4.7.0 中创建不透明的错误消息)
- 当在嵌套的lambda中使用“decltype”时,GCC的分离错误
- decltype 错误 C2440 无法从'int *'转换为'int *&'
- 如何修复模板内部重构decltype的错误
- C++11 编译器错误,后跟 decltype(var) 后跟内部类型的"var"