template <typename T>
struct A {
A(T a) : _value{a} {}
T& value() {return _value;}
// if (std::is_const<Tp>) T& value() const {return _value;}
private:
T _value;
};
int main() {
A<int> mutA{1};
cout << "mutA: " << mutA.value() << endl;
mutA.value() += 10;
cout << "mutA: " << mutA.value() << endl;
A<const int> immA{2};
cout << "immA: " << immA.value() << endl;
// error immA.value() += 10;
}
A
可以用以下任何一种实例化:-
A<int> mutableA{1};
或
A<const int> immutableA{1};
我要实现的是,如果模板参数Tp
为const
(即std::is_const<Tp>::value
为true),则将声明成员函数T& value()
为T& value() const
;
下面的代码失败,但是等效的东西会很好:-
if constexpr (std::is_const<Tp>::value) {
T& value() {return _value;}
}
else {
T& value() const {return _value;}
}
A
具有许多功能,因此两次定义它不是解决方案。
答案 0 :(得分:1)
只需声明两者,但确保const
版本仅允许const
访问:
template <typename T>
struct A {
A(T a) : _value{a} {}
T& value() {return _value;}
const T& value() const {return _value;}
private:
T _value;
};
查看用例:
void show(int);
void modify(int&);
void f1(A<int>& a) {
show(a.value());
modify(a.value());
}
好的,a.value()
在这里返回int&
,因此可以修改变量。
void f2(A<const int>& a) {
show(a.value());
// modify(a.value()); // invalid
}
即使我们在调用T& value();
,由于T
为const int
,返回类型为const int&
,并且值不能修改。
void f3(const A<int>& a) {
show(a.value());
// modify(a.value()); // invalid
}
现在我们正在调用const T& value() const
;,因此返回类型为const int&
。同样,该值不能修改。
void f4(const A<const int>& a) {
show(a.value());
// modify(a.value()); // invalid
}
此人也叫const T& value() const
。使用T=const int
时,语言“折叠”了冗余const
,因此const T
与const int
相同,返回类型为const int&
。因此该值无法修改。
答案 1 :(得分:0)
最终弄清楚了如何使用std :: enable_if做到这一点。
template <typename T>
struct A {
A(T a) : _value{a} {}
template <typename Tp = T>
std::enable_if_t<std::is_const<Tp>::value, T&> value() const {return _value;}
template <typename Tp = T>
std::enable_if_t<!std::is_const<Tp>::value, T&> value() {return _value;}
private:
T _value;
};
这是因为“替换失败不是错误(SFINAE)。”请注意,您不能直接使用模板参数T,因为必须替换才能使SFINAE起作用。提供template <typename Tp = T>
中的默认参数即可解决问题。
如果std::enable_if_t
的条件为false,则不会声明该函数。如果为true,则第二个参数T&
是std::enable_if_t
的结果。
std::enable_if_t
仅从C ++ 14起可用。如果您使用的是C ++ 11,则必须使用稍微冗长的形式typename std::enable_if<std::is_const<Tp>::value, T&>::type
。
template <typename T>
struct A {
A(T a) : _value{a} {}
template <typename Tp = T>
typename std::enable_if<std::is_const<Tp>::value, T&>::type value() const {return _value;}
template <typename Tp = T>
typename std::enable_if<!std::is_const<Tp>::value, T&>::type value() {return _value;}
private:
T _value;
};