I was just looking through implementation of non local means algorithm via google (thanks google for code search) and come across this function mirror.
template<typename T,typename U,bool N>
inline int
boundaryExpansion::helperBase<T,U,N>::mirror(const int src,
const int size,
const int last) const {
const int32 alpha(src%size);
if (alpha>=0) {
return (((src/size) & 0x00000001) != 0) ? last-alpha : alpha;
}
return (((src/size) & 0x00000001) == 0) ? -alpha-1 : size+alpha;
}
And the line I am interested in is this
const int32 alpha(src%size);
Now what is alpha here? A function or a variable? What this syntax means? Is this a variable declaration?
This is a variable declaration. A declaration of the form:
type variablename = value;
is essentially equivalent to:
type variablename(value);
This is the case regardless of what type is - whether it is a user-defined class or a built-in type. Note that the reverse is not always the case - the = syntax requires that there be an accessible copy constructor.
For similar reasons, you can cast arithmetic types using the constructor syntax, as in: x = int(42.0);
It is a variable declaration, and it is equivalent to this:
const int32 alpha = src%size;
Related
I found this gem in our codebase.
constexpr bool ConstexprStrBeginsWithImpl(const char* str, const char* subStr)
{
return !subStr[0] ? true : (str[0] == subStr[0] && ConstexprStrBeginsWithImpl(str + 1, subStr + 1));
}
template<int N, int M>
constexpr bool ConstexprStrBeginsWith(const char(&str)[N], const char(&subStr)[M])
{
static_assert(M <= N, "The substring to test is longer than the total string");
return ConstexprStrBeginsWithImpl(str, subStr);
}
Now I get what it does (comparing two constant strings as a constexpr), but what is this strange calling syntax const char(&str)[N]? to deduce the template int-parameter with the length of a constant char? How does this work? How is that a legal syntax? :-O
I thought you had to declare a constant char array parameter like this: const char str[N]?
If I use that - to me more logical - version, then my compilers (VCL and GCC) complain that they can't deduce the int-parameter N when using the constexpr as a parameter to another template with a bool. For example in this scenario:
template<bool B> struct Yada { int i = 23; };
template<> struct Yada<true> { int i = 42; };
int main()
{
Yada<ConstexprStrBeginsWith("foobar", "foo")> y;
std::cout << y.i;
}
This only compiles, if I declare str and subStr via const char(&str)[N] instead of just const char str[N].
So.... I am happy that it compiles and it looks certainly clever, but.. is this legal syntax? What is declared here? :-O. #justcurious
Greetings, Imi.
Thanks to #Thomas, #Jarod42 and #largest_prime_is_463035818, I could piece the puzzle together:
The & before the "str" is to declare a reference to an char-array instead of a char array by-value. The parenthesis are needed due to binding rules.
The reason that the template can not deduce the size of the char array if passed by-value is, that these old c-arrays are decaying to pointers, whereas references to C-arrays are never decaying. Jarod42 has a nice example of how to use templates instead - if (for some reason) you don't like to use references to c-arrays.
I was trying out codefights.com and noticed someones answer to a question which involved giving all the longest strings in a vector do this:
std::vector<std::string> r, allLongestStrings(std::vector<std::string> a) {
int b=0;
for (s:a) if (s.size()>b) b=s.size();
for (s:a) if (s.size()==b) r.push_back(s);
return r;
}
He's declaring a variable in the return type specifier for the function, can anyone tell me why this is allowed? I't doesn't compile on my machine and I couldn't find a gcc extension that does this, thanks in advance :).
Looking at the reference (decl-specifier-seq), I don't see how it would be possible to declare the return variable before the function name.
With C++14, you can use the auto keyword to remove the duplicate mentioning of the return type:
auto allLongestStrings( const std::vector<std::string>& a ) {
std::vector<std::string> r;
std::size_t b = 0;
for( const auto& s : a ) if( s.size() > b ) b = s.size();
for( const auto& s : a ) if( s.size() == b ) r.push_back( s );
return r;
}
I fixed some other things of the code:
to improve efficiency, declare the parameter a as const reference, so it won't be copied
declare b as std::size_t to match return type of std::vector::size()
in range-for loop, a type specifier is necessary (even if it is auto); added const reference for efficiency
Live demo.
The mixed variable / function declaration seems to be ok, though gcc complains that function definition shouldn't be there but I think it's ok at global scope. But it's a 100% valid syntax even in non-global scope if no function definition is given. This declaration is just regular declarations of several items of the same leading type. For example we can declare multiple items of different kinds but with same leading like this:
// single line declaration
int i = 0, * p_i = nullptr, ai[2] = {42,42}, geti(void), * * getppi(void);
// the same as
int i = 0;
int * p_i = nullptr;
int ai[2] = {42, 42};
int geti(void);
int ** getppi(void);
So r is just a regular variable of type std::vector<std::string>, followed by function allLongestStrings that returns the same std::vector type.
This compact declaration form exists for historical reasons. Basically it helped to save quite some bytes for storing and compiling the source file.
This form of for loop is probably on of the earlier experimental extensions before current form was standardized.
I'm trying to create a compile-time bit mask using metaprograming techniques, my idea is to create something like this:
unsigned int Mask3 = Mask<2>(); // value = 0x03 = b00000000000000000000000000000011
unsigned int Mask3 = Mask<3>(); // value = 0x07 = b00000000000000000000000000000111
unsigned int Mask3 = Mask<7>(); // value = 0x7F = b00000000000000000000000001111111
The code that I'm trying is this:
template <const unsigned int N> const unsigned int Mask()
{
if (N <= 1)
{
return 1;
}
else
{
return ((1 << N) | Mask<N - 1>());
}
}
return 1;
But it result in tons pairs of warnings:
warning C4554: '<<' : check operator precedence for possible error
warning C4293: '<<' : shift count negative or too big
And in the end, the compile error:
error C1202: recursive type or function dependency context too complex.
So, I deduce that the recursivity never ends and falls into a compiler infinite loop but I'm don't understanding WHY.
As has already been pointed out, you're depending on a runtime check to
stop a compile time recursion, which can't work. More importantly,
perhaps, for what you want to do, is that you're defining a function,
which has no value until you call it. So even after you stop the
recursion with a specialization, you still have a nested sequence of
functions, which will be called at runtime.
If you want full compile time evaluation, you must define a static data
member of a class template, since that's the only way a compile time
constant can appear in a template. Something like:
template <unsigned int N>
struct Mask
{
static unsigned int const value = (1 << (N - 1)) | Mask<N - 1>::value;
};
template <>
struct Mask<0>
{
static unsigned int const value = 0;
};
(I've also corrected the numerical values you got wrong.)
Of course, you don't need anything this complicated. The following
should do the trick:
template <unsigned int N>
struct Mask
{
static unsigned int const value = (1 << (N + 1)) - 1;
};
template <>
struct Mask<0>
{
static unsigned int const value = 0;
};
(You still need the specialization for 0. Otherwise, 0 means all bits
set.)
Finally, of course: to access the value, you need to write something
like Mask<3>::value. (You might want to wrap this in a macro.)
It doesn't need to be recursive. This should work just fine :
template <const unsigned int N> const unsigned int Mask()
{
return ((1 << N) - 1);
}
It doesn't even need to be a template really. An (inlined) function is ok.
Note that if you want to support any value of N, specifically N >= sizeof(unsigned int) * CHAR_BIT, you probably want to treat those as a special case.
A template is created at compile time, but you are relying on run time behavior to stop the recursion.
For example, if you instantiate Mask<2>, it is going to use Mask<1>, which is going to use Mask<0>, which is going to use Mask<-1>, etc.
You have a runtime check for N being <= 1, but this doesn't help when it's compiling. It still creates an infinite sequence of functions.
To blunt template instantiation recursion you need to introduce one explicit specialization:
template <0> const unsigned int Mask()
{
return 1;
}
Your recursion never ends, because compiler tries to generate template implementation for both if-branches. So, when it generates Mask<0> it also generates Mask<0xffffffff> and so on
C++11 -- no recursion or templates:
constexpr unsigned mask(unsigned N) { return unsigned(~(-1<<N)); }
So far the answers only addressed the second error (C1202), but you asked more than that.
Warning C4554 is caused by a Microsoft compiler bug involving template parameters and the << operator. So, (1 << N) generates a warning. If N were an ordinary parameter, there would be no warning of course.
The very simple workaround is to use (1 << (N)) instead of (1 << N), and C4554 goes away!
I'm using a template to convert integral types into a string representation of their binary values. I used the following:
template<typename T>
std::string ToBinary(const T& value)
{
const std::bitset<std::numeric_limits<T>::digits + 1> bs(value);
const std::string s(bs.to_string());
return s;
}
It works for int but doesn't compile with unsigned int :
unsigned int buffer_u[10];
int buffer_i[10];
...
ToBinary(buffer_i[1]); //compile and works
ToBinary(buffer_u[1]); //doesn't compile -- ambiguous overload
Could you explain why?
EDIT:
Yes, I'm using VS2010
Not your ToBinary call is ambiguous, its the constructor call of bitset with an unsigned value. Unfortunately this is a VC++ Bug: http://connect.microsoft.com/VisualStudio/feedback/details/532897/problems-constructing-a-bitset-from-an-unsigned-long-in-the-vc-rc
Edit - Workaround:
template<>
std::string ToBinary<unsigned int>(const unsigned int& value)
{
const std::bitset<std::numeric_limits<unsigned int>::digits> bs(static_cast<unsigned long long>(value));
return bs.to_string();
}
If you look at the standard (FDIS n3290), then you see that std::bitset has multiple constructors:
First there is this one:
20.5.1 bitset constructors [bitset.cons]
constexpr bitset(unsigned long long val) noexcept;
Effects: Constructs an object of class bitset, initializing the
first M bit positions to the corresponding bit values in val. M is the
smaller of N and the number of bits in the value representation (3.9)
of unsigned long long. If M < N, the remaining bit positions are
initialized to zero.
Then there is also this one, which I suspect might be might cause things to become ambigious, when you call it with unsigned int
template <class charT>
explicit bitset(
const charT* str,
typename basic_string<charT>::size_type n = basic_string<charT>::npos,
charT zero = charT(’0’), charT one = charT(’1’));
Effects: Constructs an object of class bitset as if by
bitset( n == basic_string<charT>::npos ? basic_string<charT>(str) :
basic_string<charT>(str, n), 0, n, zero, one)
Are you using VC10? There is already an issue reported: Microsoft connect. Also I'd guess that you might be able to fix it by casting the type to int if it is 32 bit, like this:
string s = ToBinary(*reinterpret_cast<int*>(&buffer_u[1]));
This can be done inside of the method as well if needed. The result of the reinterpret should not be used for arithmetics anymore, though. ;)
Works fine as workaround for me (but looks quite ugly)
template<typename T>
std::string ToBinary(const T& value)
{
switch (sizeof(T))
{
case 8:
return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const long*>(&value)).to_string();
case 4:
return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const int*>(&value)).to_string();
case 2:
return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const short*>(&value)).to_string();
case 1:
return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const char*>(&value)).to_string();
}
return "n/a";
}
there are probably several ways I will expose my ignorance with this question :)
First, I think this is C++ code, but the extension of the file is .C (so maybe it is C?)
Anyway, I am trying to compile a program called Sundance (Sentence UNDerstanding ANd Concept Extraction) which is a Natural Language Processing tool. The compile error I get relates to the following:
// This class is used internally to keep track of constituents that are
// potential subjects for clauses during clause handling.
class PotentialXP {
public:
Constituent* XPPtr;
unsigned int Distance;
unsigned int ClauseIndex;
unsigned int ConstIndex;
PotentialXP() {
XPPtr = 0;
Distance = 0;
ClauseIndex = 0;
ConstIndex = 0;
};
operator int() const {
return (int)XPPtr;
};
void Set(Constituent* w,
unsigned int x,
unsigned int y,
unsigned int z){
XPPtr = w;
Distance = x;
ClauseIndex = y;
ConstIndex = z;
};
};
The error is "cast from ‘Constituent* const*’ to ‘int’ loses precision"
and relates to the lines:
operator int() const {
return (int)XPPtr;
};
I understand why I get an error. XPPtr is of type Constituent*, so how can it be converted to an integer? Can anyone figure out what the author of the code wants to do here, and how I might rewrite this line so it compliles? What is an operator function (if that's what you call it) for?
Any advice much appreciated!
That compiles fine for me. You are on a 64-bit machine, where size_t is larger than int.
Explanation: you can historically convert a pointer an int
struct Foo {};
int main ()
{
Foo * f = new Foo ();
std :: cout << (int)f; // Prints 43252435 or whatever
}
If you want an integer which is the same size as a pointer, use size_t or ssize_t.
And why on earth are you writing operator int() like that anyway? Do you want operator bool() to test for validity? In which case a function body of return NULL != XPPtr would be better style -- clearer, at least.
The line operator int() const states a how your object can be cast to int.
The Constituent* can be cast to int because both types are usually the same size. I do not think that this is what the programmer intended, since the raw pointer value is of no semantic use. Maybe there should be a field lookup? E.g:
operator int() const {
return (int)XPPtr->somevalue;
};