C++ 使用模板设置类成员是否为常量

C++ 使用模板设置类成员是否为常量,c++,templates,c++17,c++20,C++,Templates,C++17,C++20,我有一个模板类,我想根据模板类型切换其中的内容是否为常量 伪代码: template<bool isConst> Class ConstableClass { public: // if isConst == true make this method const void DoSomething() "const"; // if isConst == true make the returned smartpointer type const method

我有一个模板类,我想根据模板类型切换其中的内容是否为常量

伪代码:

template<bool isConst>
Class ConstableClass
{
public:
    // if isConst == true make this method const
    void DoSomething() "const";

    // if isConst == true make the returned smartpointer type const method const
    std::unique_ptr<"const" int> operator->() "const";

private:
    // if isConst == true add const at the start of the next line
    "const" int foo;
}
模板
类ConstableClass
{
公众:
//如果isConst==true,则将此方法设为常量
void DoSomething()“const”;
//如果isConst==true,则将返回的smartpointer类型设为const method const
std::unique_ptr运算符->()“const”;
私人:
//如果isConst==true,则在下一行的开头添加const
“const”int-foo;
}

这类事情可能吗?

不,不可能按你想要的方式去做。虽然有一种方法可以操作成员变量类型和函数返回类型,但无法向方法添加/删除常量说明符。这意味着您必须为模板参数的真值和假值编写两个单独的类定义专门化。

第一个用例是不可能的。不能使函数修饰符有条件地基于某个模板。但是,我认为您尝试这样做是因为您不想在
const
和函数的常规版本之间复制和粘贴代码。在这种情况下,只需编写一个执行实际工作的
private
impl方法,并在类的
cost
和非
const
版本中使用它

private:
int&get_impl()常量{…}
公众:
const int&get()const{return get_impl();}
int&get(){return get_impl();}
剩下的是可能的,而且非常简单:

std::unique\u ptr
//我们可以通过以下方式做到这一点:
std::unique\u ptr。。。
//这可以写得更优雅,因为
模板
如果t=std::conditional,则使用const;
std::唯一的ptr;

有条件地使成员变量
const
是毫无意义的,因为不管怎样,当您使变量
const
具有类型特征和SFINAE时,这种情况已经发生了。

template <bool isConst>
class ConstableClass
{
public:
    template <bool C = isConst, typename = std::enable_if_t<C>>
    void DoSomething() const;

    template <bool C = isConst, typename = std::enable_if_t<!C>>
    void DoSomething();

    template <bool C = isConst, typename = std::enable_if_t<C>>
    std::unique_ptr<const int> operator->();

    template <bool C = isConst, typename = std::enable_if_t<!C>>
    std::unique_ptr<int> operator->();

private:
    std::conditional_t<isConst, const int, int> foo{};
};
模板
类ConstableClass
{
公众:
模板
void DoSomething()常数;
模板
无效剂量();
模板
std::unique_ptr运算符->();
模板
std::unique_ptr运算符->();
私人:
std::conditional_t foo{};
};
专业化:

template <bool isConst>
class ConstableClass
{
public:
    void DoSomething() const;

    std::unique_ptr<const int> operator->() const;

protected:
    const int foo{};
};

template <>
class ConstableClass<false>
{
public:
    void DoSomething();

    std::unique_ptr<int> operator->();

protected:
    int foo{};
};
模板
类ConstableClass
{
公众:
void DoSomething()常数;
std::unique_ptr运算符->()常量;
受保护的:
const int foo{};
};
模板
类ConstableClass
{
公众:
无效剂量();
std::unique_ptr运算符->();
受保护的:
int foo{};
};
在以下方面有限制:

模板
类ConstableClass
{
公众:
void DoSomething()常量需要isConst;
void DoSomething()不需要isConst;
std::unique_ptr运算符->()const需要isConst;
std::unique_ptr运算符->()不需要isConst;
私人:
std::conditional_t foo{};
};
我有一个模板类,我想根据模板类型切换其中的内容是否为常量。这可能吗

是的,我发现专门化更具可读性(除非您可以访问概念)。下面的示例相当明确地显示了这两种情况

template<bool isConst>
class ConstableClass;

template<>
class ConstableClass<false>
{
  int foo;
public:
  void DoSomething();
  std::unique_ptr<int> operator->();
};

template<>
class ConstableClass<true>
{
  int const foo;
public:
  ConstableClass()
    : foo{0} {} // example
  void DoSomething() const;
  std::unique_ptr<int const> operator->() const;
};
模板
类ConstableClass;
模板
类ConstableClass
{
int foo;
公众:
无效剂量();
std::unique_ptr运算符->();
};
模板
类ConstableClass
{
int const foo;
公众:
ConstableClass()
:foo{0}{}//示例
void DoSomething()常数;
std::unique_ptr运算符->()常量;
};

请记住,您确实需要为
true
案例添加构造函数,因为将
const
添加到
foo
会隐式删除它。

我正在使用C++17相关/dupe:
std::is_const
SFINAE
一起工作,还有可能
std::remove_const
std::add_const
也可以。@metablaster:不,这不是OP需要的。更确切地说,不是那些结构本身,我愿意成为一个向C++语言标准化委员会提交了一篇文章的人。就像我们没有例外(这里有一些constexpr表达式),我们可以有const(这里有一些constexpr表达式)。。。。或者对成员函数使用两种不同的重载。是的,没错,两种重载。顺便说一句,这种情况经常发生,例如,STL容器有end()和end()常量,第一个返回迭代器,第二个返回常量迭代器。
template<bool isConst>
class ConstableClass;

template<>
class ConstableClass<false>
{
  int foo;
public:
  void DoSomething();
  std::unique_ptr<int> operator->();
};

template<>
class ConstableClass<true>
{
  int const foo;
public:
  ConstableClass()
    : foo{0} {} // example
  void DoSomething() const;
  std::unique_ptr<int const> operator->() const;
};