我很困惑,我正在设计一个模板,我发现了一个奇怪的行为,用T=float&
实例化模板:
// Given an available float f:
float f = 1.0;
// This getter works for T=float&:
template <typename T>
struct test {
const T get() { return f; }
};
int main() {
float& f1 = test<float&>().get();
}
第一件奇怪的事情是,f1
应该是const float&
,因为代码是正确的,因此,我希望会出现错误,但它运行正常。
第二个奇怪的事情就是在这个类似的例子中,当我不希望它出现时报告错误:
// Given an available float f:
float f = 1.0;
struct State {
const float& get() { return f; }
};
// This does not work for T=float&:
template <typename T>
struct test2 {
State state;
const T get() { return state.get(); }
};
int main() {
const float& f2 = test2<float&>().get();
}
报告的错误是:
main.cpp: In instantiation of 'const T test2<T>::get() [with T = float&]':
main.cpp:31:41: required from here
main.cpp:22:36: error: binding reference of type 'float&' to 'const float' discards qualifiers
const T get() { return state.get(); }
这很奇怪,因为第二个例子只声明了const float&
个类型,而不是float&
而不是const float
,所以我不知道发生了什么。
也许模板不是设计用于引用或它是GCC上的错误,或者我只是在做一些愚蠢的事情。
我使用gcc (GCC) 6.3.1 20170306
和repl.it网站使用C ++ 11测试了此代码。
如果它是一个错误,我会对任何可用的工作感兴趣。
答案 0 :(得分:1)
在你的案件中也会发生同样的事情。
对于第一种情况,我们的类型是float&
。在float & const
中,const
是多余的。因此,它将仅以float &
解析。
对于第二种情况,State::get()
返回的是对const float值的引用。 test2<float&>::get()
返回的那个仍然是float&
。现在编译器会阻止你将const float分配给非const的。
答案 1 :(得分:1)
更专业。我认为这给出了你想要的行为:
template <typename T>
struct test {
T get() { return f; }
};
template <typename T>
struct test<T&> {
const T& get() { return f; }
};
测试:
int main() {
const float& f1 = test<float&>().get();
float& f2 = test<float&>().get(); //Error
const float& f3 = test<const float&>().get();
float f4 = std::move(test<float>().get());
}
答案 2 :(得分:1)
为了一些完整性,这是我可能会采用的解决方案:
template <class T>
struct make_non_modifiable { using type = const T; };
template <class T>
struct make_non_modifiable<T&> { using type = const T &; };
template <class T>
struct make_non_modifiable<T*> { using type = const T *; };
template <typename T>
struct test {
typename make_non_modifiable<T>::type get() { return f; }
};
我没有尝试编译此代码,因此可能会有一两个错误。
我通常更喜欢类模板部分特化而不是函数模板特化,因为后者在函数重载时更难理解。