我有一个简单的模板类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)
2条答案
按热度按时间rvpgvaaj1#
MSVC C++ Features声明P0734R0 Concepts可从VS 2019 16.3获得。
您可能正在使用VS 2017,它不支持MSVC的C++20吗?
23c0lvtd2#
您认为我的代码是不正确的还是Visual Studio编译器错误/不完整的功能?
code是格式良好的,并且截至2022年被所有三个主要编译器的最新版本所接受。Demo。成员函数
a
是一个模板化实体,根据temp.pre#8.3,C++20
允许使用requires-clause
和一个模板化实体,根据dcl.decl#4,其中声明:init-declarator
或member-declarator
中的可选requires子句仅在声明符声明模板化函数时才出现([dcl.fct])。出现在声明符之后时,requires子句称为尾随requires子句。尾随requires子句引入了将其constraint-logical-or-expression解释为constraint-expression所产生的constraint-expression。(强调我)
这意味着您的问题的解决方案1中给出的代码是有效的。为了参考,我也发布了下面的代码: