C++ C+;中绑定到非常量引用的常量参数+;模板

C++ C+;中绑定到非常量引用的常量参数+;模板,c++,templates,reference,constants,C++,Templates,Reference,Constants,考虑以下情况: template <typename T> void f(T& x) { .... } 编译器试图用T=const int调用f(),当然会因为x=0而出现错误消息在f()的主体内赋值。 这是来自GCC的错误消息: 但是,为什么编译器要尝试将const参数与采用非const参数的函数模板绑定 这个C++模板规则背后的原理是什么? const int cn = 10; 这意味着“cn”是常量,你不能在任何时间、任何地点更改它 更多:

考虑以下情况:

template <typename T>
void f(T& x) 
{
    ....       
}
编译器试图用
T=const int
调用
f()
,当然会因为
x=0而出现错误消息
f()
的主体内赋值。
这是来自GCC的错误消息:

但是,为什么编译器要尝试将const参数与采用非const参数的函数模板绑定

<>这个C++模板规则背后的原理是什么?

const int cn = 10;
这意味着“cn”是常量,你不能在任何时间、任何地点更改它

更多:

cia的类型与ia不同。所以T将是常数int,而不是int

typedef const int      cint;
cint cia = 10;
int ia = 10;

T将用作cint,而不是int。

您可以使用
std::enable_if
加上例如
std::is_const
,以避免
T
绑定到
const
类型

typedef const int      cint;
cint cia = 10;
int ia = 10;

关于

<这个C++模板规则背后的原理是什么?”< /P>
这可能在比亚恩的《设计与进化》一书中找到,但最常见的理由是选择规则是为了简单和统一,因此这里似乎也有:以特殊方式处理某些类型会引入不必要的复杂性。

T
绑定到
常量int

为了避免这种情况,您可以使用SFINAE:

template<typename T>
typename std::enable_if<!std::is_const<T>::value, void>::type
f(T& arg) {}
模板
typename std::enable_if::value,void>::type
f(T&arg){}
已删除功能:

template <typename T> void f(T& arg) {}
template <typename T> void f(const T&) = delete;
template void f(T&arg){
模板void f(const T&)=删除;

因为。。你让它试试?还是我错过了什么?查看错误消息中的类型,
T=const int
T
const
,在解决该问题之前,该引用不涉及。我的预期是错误处于“更高级别”,例如,无法将
const int
绑定到
f(T&)
。相反,该错误是由
f()
中的赋值引起的。如果您没有进行赋值,则不会出现错误,因此,我也不会跟随
T
不是
int
;它的
常数int
。我认为这是你正在努力克服的障碍。我认为他希望编译器不要考虑模板,因为函数不能使用常量参数,然后通过新的错误消息直接告诉你。但对于编译器编写人员来说,这是另一个步骤,好处很小。@CarlColijn:你明白我的意思了。很肯定他能处理这个问题。+1。我完全可以这样做,否则我会为
T const&
提供一个重载。我的期望是C++编译器会这样做(不需要我使用<代码> STD::Enable,如果等),因为我没有写代码> const t/< /c>,而只是<代码> t> <代码>。相反,程序员的负担在于必须使用
std::enable_if
,等等。在我看来,这并不是“以特殊方式处理某些类型”。而且当前的行为似乎引入了“不必要的复杂性”,因为要排除
const
(我没有在函数模板参数中编写),必须使用
std::enable_if
+other。@WhozCraig:感谢代码示例。你可能想写一个答案,我会投赞成票。无论如何,在我看来,我正在做更多的工作来排除
T&
const int
的绑定,相反,我希望编译器为我这样做(不需要我使用
std::enable_if
+等),因为我编写了
T&
而不是
const T&
作为
f()
parameter.@Mr.C64:根据特例规则的性质,此类规则所涉及的特例(通常)被简化。以其他地方的复杂性为代价。例如,考虑编写一个处理任何类型的单个函数模板,“代码> const ”。此外,正如其他人建议的那样,也可以使用“代码> STATICO-AsHyth(添加自定义错误消息),例如<代码> StistaYaScript(.STD::ISSconst::值),T不应该是const。已删除函数的代码>+1。我总是忘记,即使是在C++11中的外部成员fns也支持这一点。这是一个不错的选择,可以给OP更多他想要的信息(直接,看这里,你不能那样做)。
template<typename T>
typename std::enable_if<!std::is_const<T>::value, void>::type
f(T& arg) {}
template <typename T> void f(T& arg) {}
template <typename T> void f(const T&) = delete;