概念非常擅长将错误定位到“不满足约束”的代码行。
但是,我想知道是否可以在那里发布自定义信息消息。static_assert 的好处就是这种可能性。用例:任何想要帮助用户找出某个表达式不满足约束的原因的库。
这是一个简单的例子,只是为了有一些代码。您可能会争辩说,任何体面的“用户”都必须能够弄清楚编译器的注释“因为 'is_base_of<Base, C>' 评估为 false”,但更多的自定义信息不会受到伤害。肯定会有更复杂的概念。
template<typename B, typename D>
concept is_base_of = std::is_base_of_v<B, D>;
template <typename T, is_base_of<T> BaseType>
struct BaseWrapper { };
int main()
{
class Base {};
class Derived : public Base {};
class C {};
using T1 = BaseWrapper<Derived,Base>;
using T2 = BaseWrapper<C,Base>; // fails right here, but a custom message would be nice
}
Run Code Online (Sandbox Code Playgroud) 根据cppreference C++20 现在支持模板中的浮点参数。但是,我无法在该站点以及其他站点上找到任何编译器支持信息。当前的gcc主干只是这样做,其他的都是负面的。
我只想知道这是否是一个非常低优先级的功能和/或何时会得到普遍支持。
我能找到的唯一相关的东西是:P0732R2 非类型模板参数中的类类型。如果有人可以简单地解释一下,那就太好了。
玩了一下,我注意到以下代码在 MSVC 19.27 上编译
template <typename T>
concept defined = true;
template <!defined T> // <=== !!!!!!!!
inline auto constexpr Get()
{
return 5;
}
Run Code Online (Sandbox Code Playgroud)
这是怎么回事?允许这种语法是一个坏主意吗?
函数“Process”正在接受可变数量的变量类型参数。为了处理不同的情况,我已经成功地像这样重载了它:
// general case
template <typename ...Types>
void Process( const Types&... items )
// single T
template <typename T>
void Process( const T& t )
// one or more of type NVP<>
template <typename T1, typename ...Types>
void Process( const NVP<T1>& nvp1, const NVP<Types>&... nvps )
Run Code Online (Sandbox Code Playgroud)
我想要做的 - 但不能 - 如下:对于具有任意数量的类型的前导参数ATT<>后跟任意数量的情况,我需要重载NVP<>:
// any number of leading Types ATT<> followed by any number of NVP<>
template <typename ...ATypes, typename ...BTypes>
void Process( const ATT<ATypes>&... …Run Code Online (Sandbox Code Playgroud) c++ variadic-functions overload-resolution variadic-templates c++17
在该准则下constexpr everything,随着constevalC++20的引入,越来越多的代码在编译时被评估。
这导致了一个显而易见的问题:我们如何调试它?
目前唯一的提示是编译器错误。但是如果代码编译了,但仍然没有达到预期的效果怎么办。有什么工具可以帮助解决这个问题吗?有没有检查的可能?
一个相关的问题是:如何知道哪些会在编译时真正被“执行”,哪些会在有限定符的情况下保持运行。
以下代码正确确定何时Writer( t )可以调用给定的T.
template <typename T>
inline void Process( const T& t )
{
if constexpr ( std::is_invocable<decltype(Writer), const T&>::value )
{
Writer( t );
}
else { //... }
}
Run Code Online (Sandbox Code Playgroud)
但我只能让它operator()在 Writer 中定义为例如
class Writer
{
public:
operator()( const int& )
{
\\...
}
}
Run Code Online (Sandbox Code Playgroud)
如何对成员函数进行相同的检查,即检查该函数是否存在,例如Write(...)in
class Writer
{
public:
inline void Write( const int& t )
{
}
};
class Archive
{
public:
template <typename T>
inline void …Run Code Online (Sandbox Code Playgroud) 我在 std::string 周围使用了一个包装类,但是初始化/构造它的最简单/最干净/最完整的方法是什么。我需要至少 3 种方式
天真的程序员只想将任何构造自动委托给 std::string,但这不是一个特性。
struct SimpleString
{
SimpleString() = default;
template<typename T>
SimpleString( T t ) : Text( t ) { } // <==== experimental
// Alternative: are these OK
SimpleString( const char* text ) : Text( text ) { }
SimpleString( std::string&& text ) : Text( text ) { }
SimpleString( const std::string_view text ) : Text( text ) { }
std::string Text;
};
Run Code Online (Sandbox Code Playgroud)
抢先注:是的,我想要它,我需要它。用例:调用通用函数,其中 SimpleString 的处理方式与 std::string …
考虑这个简单的检查是否定义了(全局)函数:
template <typename T>
concept has_f = requires ( const T& t ) { Function( t ); };
// later use in MyClass<T>:
if constexpr ( has_f<T> ) Function( value );
Run Code Online (Sandbox Code Playgroud)
不幸的是,这允许隐式转换。这显然是一个很大的混乱风险。
问题:如何检查 Function( const T& t ) 是否“显式”存在?
就像是
if constexpr ( std::is_same_v<decltype( Function( t ) ), void> )
Run Code Online (Sandbox Code Playgroud)
应该没有隐式转换,但我无法让它工作。
注意:概念方法的重点是摆脱旧的“检测模式”并进行简化。
c++ ×8
c++20 ×5
templates ×3
c++-concepts ×2
c++17 ×2
compilation ×1
consteval ×1
constexpr ×1
function ×1
std ×1
string ×1
visual-c++ ×1
wrapper ×1