我昨天在stackoverflow中遇到了关于在不同模板类型之间实现特定转换的问题。
这是几乎提出的课程。我说几乎是因为我改变了它的一小部分,希望简化它。
#include <iostream>
#include <type_traits>
// Helper class
template<bool from, bool to>
struct ok_to_copy_foos : std::false_type {};
// Define all valid conversions as specializations:
template<>
struct ok_to_copy_foos<false, false> : std::true_type {};
template<>
struct ok_to_copy_foos<true, false> : std::true_type {};
////////////////////////////////////////////////////////////////////
template<bool Owner>
class Foo {
static constexpr bool owner_ = Owner;
public:
Foo() {}
Foo(const Foo &o)
{
static_assert(ok_to_copy_foos<Owner, Owner>::value, "can only copy from Foo<true> to Foo<false>");
}
Foo& operator=(const Foo& foo)
{
static_assert(ok_to_copy_foos<Owner, Owner>::value, "can only assign from Foo<true> to Foo<false>");
return *this;
}
template<bool U>
Foo(const Foo<U> &)
{
static_assert(ok_to_copy_foos<Owner, Owner>::value, "can only copy from Foo<true> to Foo<false>");
}
template<bool U>
Foo &operator=(const Foo<U> &)
{
static_assert(ok_to_copy_foos<Owner, Owner>::value, "can only assign from Foo<true> to Foo<false>");
return *this;
}
void bar()
{
std::cout << owner_ << " \n";
}
};
在本课程中,目的是您可以复制或分配,但结果应始终为Foo<false>
,而其他一切都是禁止的。基本上这意味着您无法从Foo<true>
复制或分配给Foo`。我不确定是否有更好的方法来实现这一目标,但这就是我现在所得到的。
然而,有些东西不会像我想的那样起作用,我希望得到一些帮助。
Foo<true> t;
auto f = t;
这将导致编译器错误,所以问题是编译器可以发现auto应该实际上是Foo<false>
吗?
答案 0 :(得分:1)
简短的回答是:不。 C ++根本不能这样工作。
auto
表示:声明的对象与初始化它的表达式相同。如果这导致编译错误,编译器不会尝试它知道的每个类,作为替代方案,看看是否有可用的转换可用于从表达式初始化它。
答案 1 :(得分:0)
正如@SamVarshavchik所写,auto
不会为你做那件事。但我想谈谈你可能想要以不同的方式解决这个问题:
我觉得你在这里过度使用模板。实质上,您的所有者模板参数是特定于实例的数据。除了其他基本考虑因素外,它应该是Foo类的数据成员。在这种情况下,您将能够轻松地赋予操作员操作权,受让人拥有所有者是假的。现在,这确实不会阻止您调用不应该工作的方法 - 因此您将抛出运行时异常而不是编译时断言 - 但如果这非常重要,您可以通过子类化实现相同的效果。
此外,为Foo
简单地设置某种代理或外观类,或者只是一个迭代器,它甚至没有用于制作副本的接口,这可能是值得的。
使用上述一个或两个建议,你甚至不需要/想要trait类,因为类定义和名称会使编译器和程序员读取代码时可以立即显而易见的是什么可以复制到什么