很多时候,我在C ++中使用了const
和mutable
概念来创建“const”或“mutable”类型的对象,(类似于iterator
vs {{1 }})。关键是要提供与其他对象不同类型的“视图”(const或可变视图)。一般的想法是mutable_object可以转换为const_object,但是const_object不能转换为mutable_object,就像const_iterator
与iterator
一样。
这很容易实现,只需创建两种类型,对于“const”类型,您可以创建一个采用可变类型的(非显式)构造函数:
const_iterator
所以,这很简单,它很好地再现了const与可变类型的C ++语义,如class mutable_object
{
public:
mutable_object() = default;
};
class const_object
{
public:
const_object() = default;
const_object(const const_object&) = default;
const_object(mutable_object m)
{ }
};
void function_that_takes_a_const_object(const_object)
{ }
void function_that_takes_a_mutable_object(mutable_object)
{ }
int main()
{
const_object c;
mutable_object m;
function_that_takes_a_const_object(c);
function_that_takes_a_const_object(m); // works
function_that_takes_a_mutable_object(m);
function_that_takes_a_mutable_object(c); // will fail
}
vs const_iterator
。
但是,我尝试使用采用可变参数模板参数的类模板类型来复制它,但无法使其工作:
iterator
在这种情况下,使用template <class... T>
struct mutable_object
{ };
template <class... T>
struct const_object
{
const_object(const const_object&) { }
const_object(mutable_object<T...>) { }
template <class... U>
const_object(mutable_object<U...>) { }
};
template <class... T>
void FOO(const_object<T...> obj)
{ }
int main()
{
mutable_object<bool,bool,int> m;
FOO(m); // fails to compile
}
调用FOO
失败,编译错误:
mutable_object<T...>
因此,模板参数替换在此失败。我不确定为什么,但我想这与需要进行多次演绎的事实有关,首先推导出test2.cpp:38:7: error: no matching function for call to ‘FOO(mutable_object<bool, bool, int>&)’
test2.cpp:38:7: note: candidate is:
test2.cpp:29:6: note: template<class ... T> void FOO(const_object<T ...>)
test2.cpp:29:6: note: template argument deduction/substitution failed:
test2.cpp:38:7: note: ‘mutable_object<bool, bool, int>’ is not derived from ‘const_object<T ...>’
的类型,然后找到合适的转换结构。
那么,有没有办法为T...
编写转换构造函数,使编译器能够正确地将函数调用绑定到mutable_object<T...> --> const_object<T...>
,我们将FOO
的实例传递给FOO
{1}}?