我观看了Bjarne Strustrup在Going Native 2013中的演讲,他给出了以下关于C++即将出现的概念特色的例子.
void sort(Container& c); // terse notation
// Expands to
template <Container __Cont>
void sort(__Cont& c); // shorthand notation
// Expands to
template <typename __Cont>
requires Container<__Cont>()
void sort(__Cont & c);
Run Code Online (Sandbox Code Playgroud)
我的问题是如何使用可变参数模板?
假设我想maximum使用Comparable概念定义可变参数函数.是否接受以下语法?
auto maximum(Comparable a)
{
return a;
}
auto maximum(Comparable c, Comparable... rest)
{
return std::max(a, maximum(rest...));
}
Run Code Online (Sandbox Code Playgroud)
如果是这样Comparable...意味着参数包中的所有元素都是相同的类型,或者只是它们都是Comparable类型,以便包可以包含int和string?(两者相当,但彼此不相同)
好奇的人想知道.
c ++概念中有什么新东西?根据我的理解,它们在功能上等同于使用static_assert,但是以"漂亮"的方式意味着编译器错误将更具可读性(因为Bjarne Stroustup说你不会得到10页或错误,而只是一个).
基本上,您可以使用概念实现的一切都是真的static_assert吗?
有什么我想念的吗?
我最近看了一下这个视频,解释了C++中概念精简版的概念,这些概念很可能在今年作为TS出现.现在,我也了解通用引用/转发引用(如描述在这里),并是t &&可以根据上下文两个方面的含义(即,如果类型推演正在执行或没有).这自然会引出概念如何与通用引用相互作用的问题?
为了使它具体化,在下面的例子中我们有
void f(int&& i) {}
int i = 0;
f(i); // error, looks for f(int&)
f(0); // fine, calls f(int&&)
Run Code Online (Sandbox Code Playgroud)
和
template <typename T>
void f(T&& test) {}
int i = 0;
f(i); // fine, calls f(T&&) with T = int& (int& && = int&)
f(0); // fine, calls f(T&&) with T = int&& (int&& && = int&&)
Run Code Online (Sandbox Code Playgroud)
但是如果我们使用概念会发生什么?
template <typename T>
requires Number<T>
void f(T&& test) {}
template <Number T>
void g(T&& test) …Run Code Online (Sandbox Code Playgroud) c++ c++-concepts universal-reference forwarding-reference c++17
目前我能想到的最好的方法是使用static_assert,但我更喜欢更好的方式.
#include <set>
#include <forward_list>
using namespace std;
template<typename C>
concept bool SizedContainer = requires (C c){
c.begin();
c.end();
{c.size()} -> size_t;
};
static_assert(SizedContainer<std::set<int>>);
static_assert(!SizedContainer<std::forward_list<int>>);
static_assert(!SizedContainer<float>);
class MyContainer{
public:
void begin(){};
void end(){};
size_t size(){return 42;};
};
static_assert(SizedContainer<MyContainer>);
int main()
{
}
Run Code Online (Sandbox Code Playgroud) #include <vector>
#include <iostream>
#include <range/v3/all.hpp>
int main()
{
auto coll = std::vector{ 1, 2, 3 };
ranges::copy(
coll,
ranges::ostream_iterator<int>{ std::cout, ", " }
); // ok
ranges::copy(
coll,
std::ostream_iterator<int>{ std::cout, ", " }
); // error
}
Run Code Online (Sandbox Code Playgroud)
问题显示在上面的代码中.我使用range-v3-0.3.7.
对我来说,通用算法copy不应该关心目标迭代器类型,只要它满足输出迭代器的要求即可.
如果是这样,为什么范围的算法不与std的迭代器兼容?
我想摆脱enable_if模板中的所有邪恶s 并用 C++20 概念替换它们,但是几乎没有关于概念的任何信息,并且几乎我阅读的任何来源的语法都发生了变化。
这是一个函数,它接受任何带有MyClass值的容器的两个迭代器:
template <class IteratorType, typename = std::enable_if<std::is_same<
typename std::iterator_traits<IteratorType>::value_type,
MyClass
>::value, void>>
void myFunction( IteratorType begin, IteratorType end ) {}
Run Code Online (Sandbox Code Playgroud)
我知道可以使用概念转换此功能,但我找不到好的线索开始。
我正在尝试定义部分专门化的类模板的成员函数,但是不同的编译器对我可以做什么以及为什么有截然不同的看法。
让我们慢慢来,从适用于所有主要编译器(all = gcc、clang 和 msvc)的东西开始:
#include <concepts>
#include <type_traits>
template <class T>
concept Integer
= std::is_same_v<T,int> || std::is_same_v<T,unsigned int>;
template <class T>
concept FloatingPoint
= std::is_same_v<T,float> || std::is_same_v<T,double>;
template <class T>
struct Foo
{
T get() {return 0;}
};
template <Integer T>
struct Foo<T>
{
T get(){ return 0; }
};
template <FloatingPoint T>
struct Foo<T>
{
T get(){ return 0; }
};
int main()
{
Foo<char>().get();
Foo<int>().get();
Foo<float>().get();
}
Run Code Online (Sandbox Code Playgroud)
很酷,但我想将成员函数的声明和定义分开。让我们将定义移到专门的类之一 …
c++ partial-specialization visual-c++ language-lawyer c++-concepts
在下面的程序中,函数foo接收v类型为 的参数std::integral_constant<bool, true>,该参数用于传入模板参数A<b>:
template <bool>
struct A{};
constexpr bool foo(auto b) {
return requires { typename A<b>; };
}
static_assert( foo( std::true_type{} ) );
Run Code Online (Sandbox Code Playgroud)
GCC 和 MSVC 都认为它有效(foo返回true),但在 Clang 中foo返回false。在线演示: https: //gcc.godbolt.org/z/j6Mnqjvbz
这里哪个编译器是正确的?
这是一个简单的例子:
#include <type_traits>
#include <ranges>
#include <vector>
struct MyClass
{
void f( int ) {}
void f( char ) {}
template <std::ranges::input_range Rng>
requires requires ( MyClass cls, const std::ranges::range_value_t<Rng>& val )
{
{ cls.f( val ) };
}
void f( Rng&& rng ) {}
};
int main()
{
MyClass cls;
cls.f( 10 );
cls.f( 'a' );
cls.f( std::vector<int>{ 10, 15 } );
}
Run Code Online (Sandbox Code Playgroud)
根据Godbolt 的说法,这个示例在 MSVC 和 GCC 上编译成功,但在 Clang 上编译失败。标准对此类要求表达式有何规定?
更新:我们可以简化示例,以便方法调用中不存在循环(Godbolt):
#include <type_traits> …Run Code Online (Sandbox Code Playgroud) c++ ×10
c++-concepts ×10
c++20 ×5
c++17 ×1
enable-if ×1
iterator ×1
range-v3 ×1
sfinae ×1
templates ×1
visual-c++ ×1