Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从模板函数内部的类型中删除常量_C++_Templates_Constants - Fatal编程技术网

C++ 从模板函数内部的类型中删除常量

C++ 从模板函数内部的类型中删除常量,c++,templates,constants,C++,Templates,Constants,那么: const int *p; Remove(p); // error related to `foo()` 模板 结构非标准{ 静态T&value(T&value){返回值;} }; 样板 结构非标准{ 静态T&value(T常量和值){返回常量转换(值);} }; 按如下方式使用: template <typename T> struct nonconst { static T& value(T& value) { return value; }

那么:

const int *p;
Remove(p); // error related to `foo()`
模板
结构非标准{
静态T&value(T&value){返回值;}
};
样板
结构非标准{
静态T&value(T常量和值){返回常量转换(值);}
};
按如下方式使用:

template <typename T>
struct nonconst {
    static T& value(T& value) { return value; }
};

template <typename T>
struct nonconst<T const> {
    static T& value(T const& value) { return const_cast<T&>(value); }
};
模板
脱空(T*p){
foo(&nonst::value(*p));
}
(或者将模板进一步专门用于(非)常量指针。)

如何:

const int *p;
Remove(p); // error related to `foo()`
模板
结构非标准{
静态T&value(T&value){返回值;}
};
样板
结构非标准{
静态T&value(T常量和值){返回常量转换(值);}
};
按如下方式使用:

template <typename T>
struct nonconst {
    static T& value(T& value) { return value; }
};

template <typename T>
struct nonconst<T const> {
    static T& value(T const& value) { return const_cast<T&>(value); }
};
模板
脱空(T*p){
foo(&nonst::value(*p));
}

(或者将模板进一步专门用于(非)常量指针。)

这将有效地获取指向常量对象的指针,并移除常量,从而使(
foo
)能够变异对象。这将与实际公开的接口不一致,这意味着它在任何类型上都能平等地(并且预期地)工作

不仅如此,它还允许您使用实际常量对象的地址调用它,这将是未定义的行为

相反,如果绝对需要(并保证对象不是const),您应该在调用模板函数之前删除constness,以便它按预期工作(而不是改变const类型)

常数A*p;
删除(const_cast(p));//'foo()的错误`

这将有效地获取指向常量对象的指针,并删除常量,从而使其(
foo
)能够变异对象。这将与实际公开的接口不一致,这意味着它在任何类型上都能平等地(并且预期地)工作

不仅如此,它还允许您使用实际常量对象的地址调用它,这将是未定义的行为

相反,如果绝对需要(并保证对象不是const),您应该在调用模板函数之前删除constness,以便它按预期工作(而不是改变const类型)

常数A*p;
删除(const_cast(p));//'foo()的错误`

如果您真的需要它,有一个/C++0x元函数:

const A *p;
Remove(const_cast<A*>(p)); // error for `foo()`
模板
脱空(T*p)
{
foo(const_cast(p));
}

测试:

如果您真的需要它,有一个/C++0x元函数:

const A *p;
Remove(const_cast<A*>(p)); // error for `foo()`
模板
脱空(T*p)
{
foo(const_cast(p));
}

测试:

您也可以首先对
常量无效*
执行
静态强制转换
,然后对
无效*
执行
常量强制转换

template<typename T>
void Remove (T *p)
{
    foo( const_cast< typename std::remove_const<T>::type *> (p) );
}
模板
脱空(T*p)
{
foo(const_cast)(static_cast(p));;
}

不可否认,它相当丑陋。

您也可以先对
常量void*
执行
静态强制转换
,然后对
void*
执行
常量强制转换

template<typename T>
void Remove (T *p)
{
    foo( const_cast< typename std::remove_const<T>::type *> (p) );
}
模板
脱空(T*p)
{
foo(const_cast)(static_cast(p));;
}

无可否认,它相当丑陋。

可能是@Kristopher的复制品,谢谢。我从那里得到了答案。还有,在
boost
中如何
std::remove_cast
的想法已经实现了。@All,谢谢回复。最后,我使用了最简单的解决方案,
foo((void*)p)我一开始没想到。可能是@Kristopher的副本,谢谢。我从那里得到了答案。还有,在
boost
中如何
std::remove_cast
的想法已经实现了。@All,谢谢回复。最后,我使用了最简单的解决方案,
foo((void*)p)这一点我一开始并不在意。我同意,但这看起来很难看,必须在多个地方进行编辑。假设我只传递了可修改的
const T*
(这不会导致任何UB)。@iammilind和你未来的维护者会感谢你的丑陋,因为它很容易追踪到,而不是“我在哪里意外地做了错误的事情,让constness在没有问我的情况下神奇地丢弃了”。如果它是“可修改的const T*”,为什么它被声明为常量?我同意Mark B的观点,这看起来像是在制造麻烦。我同意,但这看起来很难看,必须在多个地方进行编辑。假设我只传递了可修改的
const T*
(这不会导致任何UB)。@iammilind和你未来的维护者会感谢你的丑陋,因为它很容易追踪到,而不是“我在哪里意外地做了错误的事情,让constness在没有问我的情况下神奇地丢弃了”。如果它是“可修改的const T*”,为什么它被声明为常量?我同意Mark B的观点,这看起来像是在为今后的麻烦设置。如何实现
std::remove_const
发布在@KristopherHow给出的链接中
std::remove_const
是如何实现的发布在@Kristopher给出的链接中