Visual Studio 模板类中非模板成员函数的requires子句

3phpmpom  于 2022-11-17  发布在  其他
关注(0)|答案(2)|浏览(124)

我有一个简单的模板类A。我想启用一个函数,如果一些要求得到满足。

解决方案1 -requires子句

我尝试的第一个解决方案如下:

template <class T>
class A
{
public:
    void a(void) requires (same_as<T, int>)
    {
        std::cout << "a" << std::endl;
    };
};

这样做效果很好。我可以调用A<int>().a(),但不能调用A<char>().a();。此外,IntelliSense可以正确识别Visual Studio中的用法错误。
我试图将函数定义移出类,但在Visual Studio中遇到了C2511编译器错误。在GCC中,它工作正常。

template <class T>
class A
{
public:
    void a(void) requires (same_as<T, int>);
};

template <class T>
void A<T>::a(void)
requires (same_as<T, int>)
{
    std::cout << "a" << std::endl;
}

您认为我的代码是不正确的还是Visual Studio编译器错误/不完整的功能?

溶液2 -static_assert

此解决方案在某些情况下有效,但如果您尝试显式模板示例化(例如template class A<char>),当然会导致编译错误。此外,IntelliSense无法正确识别不正确的用法。

template <class T>
class A
{
public:

    void a(void);
};

template <class T>
void A<T>::a(void)
{
    static_assert(same_as<T, int>);
    std::cout << "a" << std::endl;
}

溶液3 -enable_if

(错误)

template <class T>
class A
{
public:

    template <std::enable_if_t<same_as<T, int>, bool> = true>
    void a(void);
};

template <class T>
template <std::enable_if_t<same_as<T, int>, bool>>
void A<T>::a(void)
{
    std::cout << "a" << std::endl;
}

这个解决方案和#2有同样的问题。而且,我不想添加一些乍看不懂的模板。

解决方案4 -一些奇怪的编译时继承

template <class T>
class A_base { /*common stuff*/ };

template <class T>
class A : public A_base<T>
{
public:
    A_base<T>::A_base;

    /* non-int stuff*/
};

template <>
class A<int> : public A_base<int>
{
public:
    A_base<int>::A_base;

    void a(void) {};
};

这将很好地工作,但在某些情况下可能会变得相当复杂,并且当一系列级别嵌套时,调试起来会非常不愉快。
你有什么建议/更好的解决办法吗?
先谢谢你。

编辑:

  • 解决方案#3不起作用,我犯了一个错误;
  • 我使用的是msvc 16.7.0,构建工具x64/x86(v14.27)
rvpgvaaj

rvpgvaaj1#

MSVC C++ Features声明P0734R0 Concepts可从VS 2019 16.3获得。
您可能正在使用VS 2017,它不支持MSVC的C++20吗?

23c0lvtd

23c0lvtd2#

您认为我的代码是不正确的还是Visual Studio编译器错误/不完整的功能?
code格式良好的,并且截至2022年被所有三个主要编译器的最新版本所接受。Demo。成员函数a是一个模板化实体,根据temp.pre#8.3,C++20允许使用requires-clause和一个模板化实体,根据dcl.decl#4,其中声明:

init-declaratormember-declarator中的可选requires子句仅在声明符声明模板化函数时才出现([dcl.fct])。出现在声明符之后时,requires子句称为尾随requires子句。尾随requires子句引入了将其constraint-logical-or-expression解释为constraint-expression所产生的constraint-expression。

(强调我)
这意味着您的问题的解决方案1中给出的代码是有效的。为了参考,我也发布了下面的代码:

template <class T>
class A
{
public:
    void a(void) requires (same_as<T, int>);
};
//well-formed as per C++20
template <class T>
void A<T>::a(void)
requires (same_as<T, int>)
{
    std::cout << "a" << std::endl;
}

相关问题