是否存在允许将非const模板参数类型隐式转换为const类型的规范方法?

Jas*_*n R 10 c++ c++11

我有一个函数,它接受特定模板类型的参数; 简化版可能如下所示:

#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>),但是如果可能的话我想避免重复.

Bar*_*rry 6

模板不允许转换!

当你写:

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)

  • 编程有两个难点.命名,缓存和逐个错误. (2认同)

Gui*_*cot 5

您编码的原因不起作用是因为隐式转换是在模板参数推断后应用的.所以在那种情况下,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)