I have looked at the clang-format style options https://clang.llvm.org/docs/ClangFormatStyleOptions.html but don't see any reference to c++ concepts and requires clauses. Normally I can configure clang-format to do what I want but I can't figure out how to get it to handle my concepts and requires clauses nicely:
Currently clang-format does this to my concepts:
template <typename F, typename P, typename T>
concept Accumulate_Fn = Parser<P>&& std::invocable<F, T, parser_t<P>>&&
std::same_as<T, std::invoke_result_t<F, T, parser_t<P>>>;
But I would like to put each one constraint on its own line (as it does for function arguments that get too long) so that the result would look like:
template <typename F, typename P, typename T>
concept Accumulate_Fn = Parser<P> &&
std::invocable<F, T, parser_t<P>> &&
std::same_as<T, std::invoke_result_t<F, T, parser_t<P>>>;
For a function with a requires clause, clang-format currently gives me:
template <Parser P1, Parser P2, typename T, Accumulate_Fn<P1, parser_t<P1>> F>
requires std::same_as<T, parser_t<P1>> constexpr Parser auto
separated_by(P1&& p1, P2&& p2, T&& init, F&& f)
But I would like something much closer to :
template <Parser P1, Parser P2, typename T, Accumulate_Fn<P1, parser_t<P1>> F>
requires std::same_as<T, parser_t<P1>>
constexpr Parser auto separated_by(P1&& p1, P2&& p2, T&& init, F&& f)
Are there any magical options that will make that work? I'm currently on clang-format 10.0.
As of Jul/20, Concepts are not properly supported by clang-format. There is an open issue in LLVM tracker.
Related
I want to use a C++ shared_ptr as a replacement for raw C pointers. As a simple example the following code seems to work as intended:
from libcpp.memory cimport shared_ptr, allocator
cdef shared_ptr[double] spd
cdef allocator[double] allo
spd.reset(allo.allocate(13))
The size is chosen as 13 here, but in general is not know at compile time.
I'm not sure if this is correct, but I haven't had any errors (no memory leaks and segfaults yet). I'm curious if there is a more optimal solution with make_shared.
But I can't use C++11 arrays because Cython doesn't allow literals as templates, e.g. something like
cdef shared_ptr[array[double]] spd = make_shared[array[double,13]]()
and "normal" arrays which are supposed to work with C++20 compiler (e.g. gcc 10) are causing problems in one way or another:
# Cython error "Expected an identifier or literal"
cdef shared_ptr[double[]] spd = make_shared[double[]](3)
# Can't get ptr to work
ctypedef double[] darr
cdef shared_ptr[darr] spd = make_shared[darr](13)
cdef double* ptr = spd.get() # or spd.get()[0] or <double*> spd.get()[0] or ...
Is the allocator solution the correct and best one or is there another way how to do it?
Here is what I'm going with
cdef extern from *:
"""
template <typename T>
struct Ptr_deleter{
size_t nn;
void (*free_ptr)(T*, size_t);
Ptr_deleter(size_t nIn, void (*free_ptrIn)(T*, size_t)){
this->nn = nIn;
this->free_ptr = free_ptrIn;
};
void operator()(T* ptr){
free_ptr(ptr, nn);
};
};
template <typename T>
std::shared_ptr<T> ptr_to_sptr (T* ptr, size_t nn, void (*free_ptr)(T*, size_t)) {
Ptr_deleter dltr(nn, free_ptr);
std::shared_ptr<T> sp (ptr, dltr);
return sp;
};
"""
shared_ptr[double] d_ptr_to_sptr "ptr_to_sptr"(double* ptr, size_t nn, void (*free_ptr)(double*, size_t) nogil) nogil
cdef void free_d_ptr(double* ptr, size_t nn) nogil:
free(ptr)
cdef shared_ptr[double] sp_d_empty(size_t nn) nogil:
return d_ptr_to_sptr(<double*> nullCheckMalloc(nn*sizeof(double)), nn, &free_d_ptr)
My understanding is that the "right" way to handle malloced arrays is to use a custom deleter like I did. I personally prefer sticking with somewhat-raw C pointers (double* instead of double[] or something), since it's more natural in Cython and my projects.
I think it's reasonably easy to see how to change free_ptr for more complicated data types. For simple data types it could be done in less lines and less convoluted, but I wanted to have the same base.
I like my solution in the regard that I can just "wrap" existing Cython/C code raw pointers in a shared_ptr.
When working with C++ (especially newer standards like C++20) I think verbatim code is pretty often necessary. But I've intentionally defined free_d_ptr in Cython, so it's easy to use existing Cython code to handle the actual work done to free/clear/whatever the array.
I didn't get C++11 std::arrays to work, and it's apparently not "properly" possible in Cython in general (see Interfacing C++11 array with Cython).
I didn't get double[] or similar to work either (is possible in C++20), but with verbatim C++ code I think this should be doable in Cython. I prefer more C-like pointers/arrays anyway as I said.
I am trying to perform a thrust::reduce_by_key using zip and permutation iterators.
i.e. doing this on a zipped array of several 'virtual' permuted arrays.
I am having trouble in writing the syntax for the functor density_update.
But first the setup of the problem.
Here is my function call:
thrust::reduce_by_key( dflagt,
dflagtend,
thrust::make_zip_iterator(
thrust::make_tuple(
thrust::make_permutation_iterator(dmasst, dmapt),
thrust::make_permutation_iterator(dvelt, dmapt),
thrust::make_permutation_iterator(dmasst, dflagt),
thrust::make_permutation_iterator(dvelt, dflagt)
)
),
thrust::make_discard_iterator(),
danswert,
thrust::equal_to<int>(),
density_update()
)
dmapt, dflagt are of type thrust::device_ptr<int> and dvelt , dmasst and danst are of type
thrust::device_ptr<double>.
(They are thrust wrappers to my raw cuda arrays)
The arrays mapt and flagt are both index vectors from which I need to perform a gather operation from the arrays dmasst and dvelt.
After the reduction step I intend to write my data to the danswert array. Since multiple arrays are being used in the reduction, obviously I am using zip iterators.
My problem lies in writing the functor density_update which is binary operation.
struct density_update
{
typedef thrust::device_ptr<double> ElementIterator;
typedef thrust::device_ptr<int> IndexIterator;
typedef thrust::permutation_iterator<ElementIterator,IndexIterator> PIt;
typedef thrust::tuple< PIt , PIt , PIt, PIt> Tuple;
__host__ __device__
double operator()(const Tuple& x , const Tuple& y)
{
return thrust::get<0>(*x) * (thrust::get<1>(*x) - thrust::get<3>(*x)) + \
thrust::get<0>(*y) * (thrust::get<1>(*y) - thrust::get<3>(*y));
}
};
The value being returned is a double . Why the binary operation looks like the above functor is
not important. I just want to know how I would go about correcting the above syntactically.
As shown above the code is throwing a number of compilation errors. I am not sure where I have gone wrong.
I am using CUDA 4.0 on GTX 570 on Ubuntu 10.10
density_update should not receive tuples of iterators as parameters -- it needs tuples of the iterators' references.
In principle you could write density_update::operator() in terms of the particular reference type of the various iterators, but it's simpler to have the compiler infer the type of the parameters:
struct density_update
{
template<typename Tuple>
__host__ __device__
double operator()(const Tuple& x, const Tuple& y)
{
return thrust::get<0>(x) * (thrust::get<1>(x) - thrust::get<3>(x)) + \
thrust::get<0>(y) * (thrust::get<1>(y) - thrust::get<3>(y));
}
};
In the clang_complete.txt(the help file), it shows these in clang_complete-compl_kinds:
2.Completion kinds *clang_complete-compl_kinds*
Because libclang provides a lot of information about completion, there are
some additional kinds of completion along with standard ones (see >
:help complete-items for details):
'+' - constructor
'~' - destructor
'e' - enumerator constant
'a' - parameter ('a' from "argument") of a function, method or template
'u' - unknown or buildin type (int, float, ...)
'n' - namespace or its alias
'p' - template ('p' from "pattern")
the question are:
1. i cannot access the complete-items(no this file)
2. can someone tell me how to use the parameter '+' 'a' and so on.
3. or can you tell me how to show function parameters when ( is typed.
thanks!
(forgive my poor english)
It's been a long time, but i'll answer to help future visitors.
I don't fully understand your questions, but I'll answer the 3rd one. Clang complete only launches automatic suggestion/completion when writing '.', '->' or '::', but you can launch it manually.
I use it this way. In this source:
#include <iostream>
using namespace std;
void ExampleFunc (float foo, int &bar)
{
cout << foo;
bar++;
}
int main (int argc, char **argv)
{
int a(0);
Exa[cursor here]
return 0;
}
Writing "Exa" you can press <C-X><C-U> and you will get a preview window with:
Example (float foo, int &bar)
and a completion window (the same that appears when you press <C-N> (CTRL-N) in insert mode) with:
Example f void Example(float foo, int &bar)
If there are several matches, you can move down or up with <C-N> or <C-P> and complete with <CR> (enter).
The completion is not perfect, but it should work for many other cases, for example (as you mentioned) templates:
#include <vector>
using namespace std;
int main (int argc, char **argv)
{
struct MyType {int asdf; float qwer;};
vector<MyType> vec;
ve // suggestions after <C-X><C-U>:
// "vec v vector<MyType> vec" v is for variable
// "vector p vector<Typename _Tp>" p is for pattern (template)
// constructors with its parameters, etc.
vec. // auto-fired suggestions: all std::vector methods
vec[0]. // auto-fired suggestions: "asdf", "qwer" and MyType methods
return 0;
}
If those examples don't work for you, you haven't installed the plugin properly.
By the way, you can map <C-X><C-U> to other shortcut.
I'm trying to overload make_uint4 in the following manner:
namespace A {
namespace B {
inline __host__ __device__ uint4 make_uint4(uint2 a, uint2 b) {
return make_uint4(a.x, a.y, b.x, b.y);
}
}
}
But when I try to compile it, nvcc returns an error:
error: no suitable constructor exists to convert from "unsigned int" to "uint2"
error: no suitable constructor exists to convert from "unsigned int" to "uint2"
error: too many arguments in function call
All these errors point to the "return…" line.
I was able to get a partial repro on VS 2010 and CUDA 4.0 (the compiler built the code OK but Intellisense flagged the error you are seeing). Try the following:
#include "vector_functions.h"
inline __host__ __device__ uint4 make_uint4(uint2 a, uint2 b)
{
return ::make_uint4(a.x, a.y, b.x, b.y);
}
This fixed it for me.
I have no problem compiling it in Visual Studio+nvcc. What compiler are you using?
If that would be of any help: make_uint4 is defined in vector_functions.h, line 170 as
static __inline__ __host__ __device__ uint4 make_uint4(unsigned int x, unsigned int y, unsigned int z, unsigned int w)
{
uint4 t; t.x = x; t.y = y; t.z = z; t.w = w; return t;
}
Update:
I get similar error when I try to overload the function while being inside my custom namespace. Are you certain you are not inside one? If so, try putting :: in front of function call to refer to global scope, i.e:
return ::make_uint4(a.x, a.y, b.x, b.y);
I don't have the library code, but it seems like the compiler doesn't like overloaded device functions (as they are treated just like really fancy inline macros). What is does is shadow (hide) the old make_uint4(a,b,c,d) with your new make_uint4(va, vb) and try to call the latter with 4 uint parameters. That doesn't work because there is no conversion from uint to uint2 (as indicated by the first two error messages) and there are 4 instead of 2 arguments (the last error message).
Use a slightly different function name like make_uint4_from_uint2s and you'll be fine.
Partial template specialization is one of the most important concepts for generic programming in C++. For example: to implement a generic swap function:
template <typename T>
void swap(T &x, T &y) {
const T tmp = x;
y = x;
x = tmp;
}
To specialize it for a vector to support O(1) swap:
template <typename T, class Alloc>
void swap(vector<T, Alloc> &x, vector<T, Alloc> &y) { x.swap(y); }
So you can always get optimal performance when you call swap(x, y) in a generic function;
Much appreciated, if you can post the equivalent (or the canonical example of partial specialization of the language if the language doesn't support the swap concept) in alternative languages.
EDIT: so it looks like many people who answered/commented really don't known what partial specialization is, and that the generic swap example seems to get in the way of understanding by some people. A more general example would be:
template <typename T>
void foo(T x) { generic_foo(x); }
A partial specialization would be:
template <typename T>
void foo(vector<T> x) { partially_specialized_algo_for_vector(x); }
A complete specialization would be:
void foo(vector<bool> bitmap) { special_algo_for_bitmap(bitmap); }
Why this is important? because you can call foo(anything) in a generic function:
template <typename T>
void bar(T x) {
// stuff...
foo(x);
// more stuff...
}
and get the most appropriate implementation at compile time. This is one way for C++ to achieve abstraction w/ minimal performance penalty.
Hope it helps clearing up the concept of "partial specialization". In a way, this is how C++ do type pattern matching without needing the explicit pattern matching syntax (say the match keyword in Ocaml/F#), which sometimes gets in the way for generic programming.
D supports partial specialization:
Language overview
Template feature comparison (with C++ 98 and 0x).
(scan for "partial" in the above links).
The second link in particular will give you a very detailed breakdown of what you can do with template specialization, not only in D but in C++ as well.
Here's a D specific example of swap. It should print out the message for the swap specialized for the Thing class.
import std.stdio; // for writefln
// Class with swap method
class Thing(T)
{
public:
this(T thing)
{
this.thing = thing;
}
// Implementation is the same as generic swap, but it will be called instead.
void swap(Thing that)
{
const T tmp = this.thing;
this.thing = that.thing;
that.thing = tmp;
}
public:
T thing;
}
// Swap generic function
void swap(T)(ref T lhs, ref T rhs)
{
writefln("Generic swap.");
const T tmp = lhs;
lhs = rhs;
rhs = tmp;
}
void swap(T : Thing!(U))(ref T lhs, ref T rhs)
{
writefln("Specialized swap method for Things.");
lhs.swap(rhs);
}
// Test case
int main()
{
auto v1 = new Thing!(int)(10);
auto v2 = new Thing!(int)(20);
assert (v1.thing == 10);
assert (v2.thing == 20);
swap(v1, v2);
assert (v1.thing == 20);
assert (v2.thing == 10);
return 0;
}
I am afraid that C# does not support partial template specialization.
Partial template specialization means:
You have a base class with two or more templates (generics / type parameters).
The type parameters would be <T, S>
In a derived (specialized) class you indicate the type of one of the type parameters.
The type parameters could look like this <T, int>.
So when someone uses (instantiates an object of) the class where the last type parameter is an int, the derived class is used.
Haskell has overlapping instances as an extension:
class Sizable a where
size :: a -> Int
instance Collection c => Sizable c where
size = length . toList
is a function to find size of any collection, which can have more specific instances:
instance Sizable (Seq a) where
size = Seq.length
See also Advanced Overlap on HaskellWiki.
Actually, you can (not quite; see below) do it in C# with extension methods:
public Count (this IEnumerable<T> seq) {
int n = 0;
foreach (T t in seq)
n++;
return n;
}
public Count (this T[] arr) {
return arr.Length;
}
Then calling array.Count() will use the specialised version. "Not quite" is because the resolution depends on the static type of array, not on the run-time type. I.e. this will use the more general version:
IEnumerable<int> array = SomethingThatReturnsAnArray();
return array.Count();
C#:
void Swap<T>(ref T a, ref T b) {
var c = a;
a = b;
b = c;
}
I guess the (pure) Haskell-version would be:
swap :: a -> b -> (b,a)
swap a b = (b, a)
Java has generics, which allow you to do similar sorts of things.