【发布时间】:2014-01-15 18:06:01
【问题描述】:
考虑以下代码:
#include <boost/range.hpp>
#include <boost/iterator/counting_iterator.hpp>
typedef boost::iterator_range<boost::counting_iterator<int>> int_range;
template <typename T>
class Ref {
T* p_;
public:
Ref(T* p) : p_(p) { }
/* possibly other implicit conversion constructors,
but no unconstrained template constructors that don't
use the explicit keyword... */
operator T*() const { return p_; }
operator const T*() const { return p_; }
};
struct Bar { };
class Foo {
public:
Foo(int a, char b) { /* ... */ }
Foo(int a, const Ref<Bar>& b) { /* ... */ }
Foo(int a, const int_range& r) { /* ... */ }
};
int main() {
Bar b;
Foo f(5, &b);
return 0;
}
此代码无法编译,因为Foo 构造函数的使用不明确,因为boost::iterator_range 显然有一个模板化构造函数,它接受单个参数并且未声明为explicit。假设更改 Ref 的结构不是一种选择,我该如何解决这个问题?我想出了以下可能的解决方案,但它很难看且不易维护,尤其是如果Foo 的构造函数不止几个:
template<typename range_like>
Foo(
int a,
const range_like& r,
typename std::enable_if<
not std::is_convertible<range_like, Ref<Bar>>::value
and std::is_convertible<range_like, int_range>::value,
bool
>::type unused = false
) { /* ... */ }
或类似
template<typename range_like>
Foo(
int a,
const range_like& r,
typename std::enable_if<
std::is_same<typename std::decay<range_like>::type, int_range>::value,
bool
>::type unused = false
) { /* ... */ }
它的缺点是int_range 的所有其他隐式类型转换都被禁用,因此依赖于boost 的未指定功能(我的直觉告诉我这可能是个坏主意)。有一个更好的方法吗? (除了 C++14 “concepts-lite”,我认为这确实是这个问题想要的)。
【问题讨论】:
-
添加一个
Foo(int, Bar*)构造函数,也许? -
@IgorTandetnik 不错的想法,但这并不能解决我试图解决的更普遍的问题。与实际解决方案相比,示例的简单性更是一个问题。
-
举个例子来说明这个你试图解决的更普遍的问题怎么样?
-
报告要提升的错误?
-
@IgorTandetnik 这个例子运行良好。假设还有其他东西可以转换为
Ref<Bar>。不是无限数量的东西,就像模板化的构造函数一样,但不仅仅是指向Bar的指针。我将在Ref类中添加一个/* ... */来表明这一点。
标签: c++ boost c++11 constructor implicit-conversion