如何约束模板参数

How to constrain template parameters

本文关键字:参数 约束 何约束      更新时间:2023-10-16

我想创建一个仅接受某些类型参数的模板。对于所有剩余类型,我希望产生编译时错误消息。所以我写了以下

-------版本1 -------

template <typename T_,bool isError = true>
struct Error {
    static_assert(!isError, "Invalid Type");
};
template <typename T_>
struct Wrapper : Error <T_> {
private:
    T_ value_;
};
template <>
struct Wrapper<int> : Error<int, false> {
private:
    int value_;
};
int main()
{
    Wrapper<int> wi;
    Wrapper<long> wl;  // I get the Invalid Type.
}

由于我没有使用类型参数T_,因此我已将其删除并停止工作。

-------版本2 -------

template <bool isError = true> 
struct Error {
    static_assert(!isError, "Invalid Type");
};
template <typename T_>
struct Wrapper : Error <> {
private:
    T_ value_;
};
template <>
struct Wrapper<int> : Error<false> {
private:
    int value_;
};
int main()
{
    Wrapper<int> wi;   // I get Invalid type ?????
    Wrapper<long> wl;  // I get the Invalid Type.
}

我的问题是。为什么在删除类型参数后会发生这种情况?该解决方案是"干净"吗?还是有更好的方法来实现我的意图?

一旦有:

template <typename T_>
struct Wrapper : Error <> {
private:
    T_ value_;
};

我们可以看到Error<>已完全指定(即,所有模板参数均已知道),这与在仍然依赖的位置不同。因此,编译器实际上会继续并无条件实例化Error<>,这意味着此代码永远不会编译(即使根本没有提及Wrapper)。当Error仍然依赖T时,它是一种依赖类型,因此仅当Wrapper<T>需要它的情况下是由情况实例化的。

我可能会以不同的方式分开特征:

template <class T>
struct my_trait : std::false_type {};
template <>
struct my_trait<int> : std::true_type {};
template <class T>
struct Wrapper {
    static_assert(my_trait<T>::value, "");
};
int main()
{
    Wrapper<int> wi;
    Wrapper<long> wl;  // I get the Invalid Type.
}

如果您真的想重复使用错误消息,则可以做类似的事情:

template <typename T>
struct Error {
    static_assert(my_trait<T>::value, "Invalid Type");
};
template <class T>
struct Wrapper {
  static constexpr auto unused = Error<T>{};
};