我有一个函数,它接受特定模板类型的参数; 简化版可能如下所示:
#include <type_traits>
template <typename T>
struct foo
{
// default constructor
foo() { }
// simple copy constructor that can construct a foo<T> from a foo<T>
// or foo<const T>
foo(const foo<typename std::remove_const<T>::type> &) { }
};
Run Code Online (Sandbox Code Playgroud)
在功能上,foo行为类似于a shared_ptr<T>,具有与此问题无关的一些其他插件功能.该函数的语义规定它更喜欢接受a foo<const T>.foo<const T>是隐式可构造的foo<T>,所以我希望能够做如下的事情:
template <typename T>
void bar(foo<const T> f) { }
int main()
{
bar(foo<const int>()); // fine
bar(foo<int>()); // compile error
}
Run Code Online (Sandbox Code Playgroud)
这失败了,因为没有匹配的重载,bar因为a foo<int>(即使a foo<const int>可以隐式构造一个foo<int>,与模板实例化一致的重载决策似乎比这更严格.
是否有规范的方法来实现这一目标?我知道我可以引入第二个重载bar(),需要foo<T>手动调度bar(foo<const T>),但是如果可能的话我想避免重复.
模板不允许转换!
当你写:
template <typename T>
void bar(foo<const T> f) { }
Run Code Online (Sandbox Code Playgroud)
bar接受foo<const T>任何一个T.它什么都不接受.foo<int>可以转换为无关紧要,foo<const int>从不考虑转换.完全停止.
如果你想把收到的东西f视为const,你可以有条件地做到const:
// convert this version
template <class T> foo<T const> make_const_f(foo<T> const& rhs) { return {rhs}; }
// pass this version through
template <class T> foo<T const>& make_const_f(foo<T const>& rhs) { return rhs; }
template <typename T>
void bar(foo<T> f) {
auto&& const_f = make_const_f(f);
// if T was const, const_f is a reference to f
// if T wasn't const, const_f is a new object of type foo<T const>
}
Run Code Online (Sandbox Code Playgroud)
您编码的原因不起作用是因为隐式转换是在模板参数推断后应用的.所以在那种情况下,foo<int>确实不会匹配foo<const T>,编译器将无法推断出它T是什么.您可以自己尝试检查直接指定类型:
int main()
{
bar(foo<const int>()); // fine
bar<int>(foo<int>()); // also fine
}
Run Code Online (Sandbox Code Playgroud)
你可以做的是让编译器采用任何类型:
template <typename T> // T might be foo<int>
void bar(T f) { }
Run Code Online (Sandbox Code Playgroud)
或者如果你想,你可以让编译器推导出T没有const 的内部:
template <typename T> // can deduce T as const int
void bar(foo<T> f) { }
Run Code Online (Sandbox Code Playgroud)
如果你真的想要强制执行constness(即使在通用代码中),你可能想要在你的类中添加一个实用程序函数,如下所示:
foo<const T> as_const() const { return *this; }
Run Code Online (Sandbox Code Playgroud)
所以当你使用泛型函数时,你可以发送你的类的const版本:
bar<int>(foo<int>{}.as_const());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
190 次 |
| 最近记录: |