Many times when I compile something with a typo or some other typing mismatch, I get the standard "error: no match for 'functionname' in ..." error. This is great. Then, especially in the case of overloaded functions and operators, g++ goes on and list like 10 pages of candidates which are just hideous and massive template definitions.
The error message is great, but is there any way to disable it from suggesting other functions variants?
As far as I know, there is no compilation flag in GCC to disable the suggested candidates in case of ambiguous function calls.
Your only hope is perhaps to patch the GCC source code.
Digging in it (version: 4.7.1), I've found what appear to be the relevant function in gcc/cp/pt.c:
void
print_candidates(tree fns)
{
const char *str = NULL;
print_candidates_1 (fns, false, &str);
gcc_assert (str == NULL);
}
As an educated guess, I think that you only need to comment out the function body.
Does -Wfatal-errors do what you want?
It stops all errors after the first one, which is not the same as simply suppressing the candidate function notes, but it reduces the output significantly:
$ cat a.cc
void f() { }
void f(int) { }
void f(char) { }
int main()
{
f((void*)0);
}
$ g++ a.cc
a.cc: In function ‘int main()’:
a.cc:7: error: call of overloaded ‘f(void*)’ is ambiguous
a.cc:2: note: candidates are: void f(int) <near match>
a.cc:3: note: void f(char) <near match>
$ g++ a.cc -Wfatal-errors
a.cc: In function ‘int main()’:
a.cc:7: error: call of overloaded ‘f(void*)’ is ambiguous
compilation terminated due to -Wfatal-errors.
Or, if you wanted to patch GCC, this adds a -fno-candidate-functions switch:
--- gcc/c-family/c.opt.orig 2012-07-11 16:37:29.373417154 +0000
+++ gcc/c-family/c.opt 2012-07-11 17:09:47.340418384 +0000
## -752,6 +752,10 ##
fbuiltin-
C ObjC C++ ObjC++ Joined
+fcandidate-functions
+C++ ObjC++ Var(flag_candidates) Init(1)
+-fno-candidate-functions Do not print candidate functions when overload resolution fails
+
fcheck-new
C++ ObjC++ Var(flag_check_new)
Check the return value of new
--- gcc/cp/call.c.orig 2012-07-11 17:08:34.186424089 +0000
+++ gcc/cp/call.c 2012-07-11 17:09:51.843444951 +0000
## -3317,6 +3317,9 ##
for (n_candidates = 0, cand1 = candidates; cand1; cand1 = cand1->next)
n_candidates++;
+ if (!flag_candidates)
+ return;
+
inform_n (loc, n_candidates, "candidate is:", "candidates are:");
for (; candidates; candidates = candidates->next)
print_z_candidate (loc, NULL, candidates);
--- gcc/cp/pt.c.orig 2012-07-11 16:37:35.658636650 +0000
+++ gcc/cp/pt.c 2012-07-11 17:10:20.910435942 +0000
## -1751,9 +1751,12 ##
void
print_candidates (tree fns)
{
- const char *str = NULL;
- print_candidates_1 (fns, false, &str);
- gcc_assert (str == NULL);
+ if (flag_candidates)
+ {
+ const char *str = NULL;
+ print_candidates_1 (fns, false, &str);
+ gcc_assert (str == NULL);
+ }
}
/* Returns the template (one of the functions given by TEMPLATE_ID)
My answer is not as cool as a patch. If you want a less verbose error message, this script will remove the ugly code, and just leave the line number for the candidates.
g++ test.cc 2>&1 | sed 's/^\([^ ]*:[0-9]*: note\):.*/\1/'
So, it can be used in a script like this:
#!/bin/bash
GXX=/usr/bin/g++
ARGS=()
i=0
show_notes=yes
for arg in "$#" ; do
if [ "$arg" = "-fterse-notes" ] ; then
show_notes=no
elif [ "$arg" = "-fno-terse-notes" ] ; then
show_notes=yes
else
ARGS[$i]="$arg"
i=$[i+1]
fi
done
if [ $show_notes = yes ] ; then
exec ${GXX} "${ARGS[#]}"
else
exec ${GXX} "${ARGS[#]}" 2>&1 | sed 's/^\([^ ]*:[0-9]*: note\):.*/\1/'
fi
If the name of this script is g++ and in your path, it should work as if you have added a command line option called -fterse-notes.
Related
I have a RcppEigen project that I'm trying to update documentation for. This project only exports one c++ function into R.
Unfortunately, I get a problem when I run either devtools::document(pkg = "~/pfexamplesinr/") or roxygen2::roxygenize(roclets="rd", package.dir = "pfexamplesinr/") The error message is below.
It says something about System command 'R' failed. The entire build output is too large to paste (I go over the character limit). If I search for the first error, it's RcppExports.cpp:15:21: error: ‘Map’ was not declared in this scope. Is there some funny business about the order of #include directives and // [[Rcpp::depends(RcppEigen)]] statements?
Note: the code builds fine when I use Rcpp::sourceCpp('pfexamplesinr/src/likelihoods.cpp')
Edit: this problem goes away when I remove the #using statements, and prepend Eigen:: whenever necessary.
#include <RcppEigen.h>
#include "svol_sisr_hilb.h"
#include "resamplers.h"
// [[Rcpp::depends(RcppEigen)]]
// choose number of particles, and number of bits for inverse Hilbert curve map
#define NP 500
#define NB 5
#define debug_mode false
using Eigen::Map;
using Eigen::MatrixXd;
using Eigen::VectorXd;
using hilb_sys_resamp_T = pf::resamplers::sys_hilb_resampler<NP,1,NB,double>;
using svol_pfilter = svol_sisr_hilb<NP,NB, hilb_sys_resamp_T, double, debug_mode>;
// helpful notes:
// 1.
// parameters passed to svol_pfilter() ctor are in the following order: phi, beta, sigma
// 2.
// uProposal will be dimension (time X (particles + 1))
// first NP columns will be used for state sampling
// last column will be used for resampling at each time point
// 3.
// choosing NP or NB too large will result in stackoverflow
// number of particles is set in two places: in the #define directive and also used in your R script
// [[Rcpp::export]]
double svolApproxLL(const Map<VectorXd> y, const Map<VectorXd> thetaProposal, const Map<MatrixXd> uProposal) {
// construct particle filter object
svol_pfilter pf(thetaProposal(0), thetaProposal(1), thetaProposal(2)); // order: phi, beta, sigma
// iterate over the data
double log_like(0.0);
Eigen::Matrix<double,1,1> yt;
std::array<Eigen::Matrix<double,1,1>, NP> uStateTransition;
Eigen::Matrix<double,1,1> uResample;
for(int time = 0; time < y.rows(); ++time){
// change types of inputs
yt(0) = y(time);
for(unsigned particle = 0; particle < NP; ++particle) {
uStateTransition[particle] = uProposal.block(time,particle,1,1);
}
uResample(0) = uProposal(time,NP);
// std::cout << yt.transpose() << "\n";
// for(unsigned int i = 0; i < NP; ++i)
// std::cout << uStateTransition[i] << ", ";
// std::cout << "\n----------\n";
// update particle filter and log-likelihood
pf.filter(yt, uStateTransition, uResample);
log_like += pf.getLogCondLike();
}
//return es.eigenvalues();
return log_like;
}
// You can include R code blocks in C++ files processed with sourceCpp
// (useful for testing and development). The R code will be automatically
// run after the compilation.
/*** R
numTime <- 3
numParts <- 500 # make sure this agrees with NP
u <- matrix(rnorm(numTime*(numParts+1)), ncol = numParts+1)
params <- c(.9, 1, .1) # -1 < phi < 1, beta, sigma > 0
hist(replicate(100, svolApproxLL(rnorm(numTime), params, u)))
*/
Error in (function (command = NULL, args = character(), error_on_status = TRUE, :
System command 'R' failed, exit status: 1, stdout + stderr (last 10 lines):
E> /home/taylor/R/x86_64-pc-linux-gnu-library/4.1/RcppEigen/include/Eigen/src/Core/MatrixBase.h:48:34: required from ‘class Eigen::MatrixBase<Eigen::Matrix<double, -1, 1> >’
E> /home/taylor/R/x86_64-pc-linux-gnu-library/4.1/RcppEigen/include/Eigen/src/Core/PlainObjectBase.h:98:7: required from ‘class Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1> >’
E> /home/taylor/R/x86_64-pc-linux-gnu-library/4.1/RcppEigen/include/Eigen/src/Core/Matrix.h:178:7: required from ‘class Eigen::Matrix<double, -1, 1>’
E> /home/taylor/R/x86_64-pc-linux-gnu-library/4.1/Rcpp/include/Rcpp/InputParameter.h:77:11: required from ‘class Rcpp::ConstReferenceInputParameter<Eigen::Matrix<double, -1, 1> >’
E> RcppExports.cpp:43:74: required from here
E> /home/taylor/R/x86_64-pc-linux-gnu-library/4.1/RcppEigen/include/Eigen/src/Core/DenseCoeffsBase.h:5
Thanks for providing the URL to the repro. This error, as it happens not infrequently, appears to be one deeper down 'hidden' by devtools::document().
When I clone your repo onto a machine with 'current everything' from CRAN running Ubuntu 21.04 and doing my usual two-step of
compAttr.r # shell wrapper for Rcpp::compileAttributes
roxy.r -f # shell wrapper for roxygenize()
(using these helper scripts from my littler package),
I end in tears because your code uses C++17 statements without specifying C++17 as a compilation standard.
In other words, a vanilla bug at your end, independent of Rcpp or other tools.
edd#rob:~/git/stackoverflow/68985867/pfexamplesinr(master)$ compAttr.r
edd#rob:~/git/stackoverflow/68985867/pfexamplesinr(master)$ roxy.r -f
ℹ Loading pfexamplesinr
Exports from /home/edd/git/stackoverflow/68985867/pfexamplesinr/src/likelihoods.cpp:
double svolApproxLL(Eigen::Map<Eigen::VectorXd> y, Eigen::Map<Eigen::VectorXd> thetaProposal, Eigen::Map<Eigen::MatrixXd> uProposal)
Exports from /home/edd/git/stackoverflow/68985867/pfexamplesinr/src/rcppeigen_hello_world.cpp:
Eigen::MatrixXd rcppeigen_hello_world()
Eigen::MatrixXd rcppeigen_outerproduct(const Eigen::VectorXd& x)
double rcppeigen_innerproduct(const Eigen::VectorXd& x)
Rcpp::List rcppeigen_bothproducts(const Eigen::VectorXd& x)
Exports from /home/edd/git/stackoverflow/68985867/pfexamplesinr/src/resamplers.h:
Exports from /home/edd/git/stackoverflow/68985867/pfexamplesinr/src/rv_eval.h:
Exports from /home/edd/git/stackoverflow/68985867/pfexamplesinr/src/rv_samp.h:
/home/edd/git/stackoverflow/68985867/pfexamplesinr/src/RcppExports.cpp updated.
/home/edd/git/stackoverflow/68985867/pfexamplesinr/R/RcppExports.R updated.
Re-compiling pfexamplesinr
─ installing *source* package ‘pfexamplesinr’ ...
** using staged installation
** using staged installation
** libs
ccache g++ -std=gnu++14 -I"/usr/share/R/include" -DNDEBUG -I'/usr/local/lib/R/site-library/Rcpp/include' -I'/usr/local/lib/R/site-library/RcppEigen/include' -fpic -g -O3 -Wall -pipe -pedantic -Wno-misleading-indentation -Wno-unused -Wno-ignored-attributes -Wno-class-memaccess -c RcppExports.cpp -o RcppExports.o
ccache g++ -std=gnu++14 -I"/usr/share/R/include" -DNDEBUG -I'/usr/local/lib/R/site-library/Rcpp/include' -I'/usr/local/lib/R/site-library/RcppEigen/include' -fpic -g -O3 -Wall -pipe -pedantic -Wno-misleading-indentation -Wno-unused -Wno-ignored-attributes -Wno-class-memaccess -c likelihoods.cpp -o likelihoods.o
In file included from svol_sisr_hilb.h:8,
from likelihoods.cpp:1:
sisr_filter.h: In member function ‘void pf::filters::SISRFilter<nparts, dimx, dimy, resamp_t, float_t, debug>::filter(const osv&, const std::vector<std::function<const Eigen::Matrix<float_t, -1, -1>(const Eigen::Matrix<float_t, dimx, 1>&)> >&)’:
sisr_filter.h:229:16: warning: ‘if constexpr’ only available with ‘-std=c++17’ or ‘-std=gnu++17’
229 | if constexpr(debug)
| ^~~~~~~~~
sisr_filter.h:262:16: warning: ‘if constexpr’ only available with ‘-std=c++17’ or ‘-std=gnu++17’
262 | if constexpr(debug)
| ^~~~~~~~~
sisr_filter.h:288:16: warning: ‘if constexpr’ only available with ‘-std=c++17’ or ‘-std=gnu++17’
288 | if constexpr(debug)
| ^~~~~~~~~
sisr_filter.h:320:16: warning: ‘if constexpr’ only available with ‘-std=c++17’ or ‘-std=gnu++17’
320 | if constexpr(debug)
| ^~~~~~~~~
sisr_filter.h: In member function ‘void pf::filters::SISRFilterCRN<nparts, dimx, dimy, dimu, dimur, resamp_t, float_t, debug>::filter(const osv&, const arrayUs&, const usvr&, const std::vector<std::function<const Eigen::Matrix<float_t, -1, -1>(const Eigen::Matrix<float_t, dimx, 1>&)> >&)’:
sisr_filter.h:559:16: warning: ‘if constexpr’ only available with ‘-std=c++17’ or ‘-std=gnu++17’
559 | if constexpr(debug)
| ^~~~~~~~~
sisr_filter.h:592:16: warning: ‘if constexpr’ only available with ‘-std=c++17’ or ‘-std=gnu++17’
592 | if constexpr(debug)
| ^~~~~~~~~
sisr_filter.h:618:16: warning: ‘if constexpr’ only available with ‘-std=c++17’ or ‘-std=gnu++17’
618 | if constexpr(debug)
| ^~~~~~~~~
sisr_filter.h:650:16: warning: ‘if constexpr’ only available with ‘-std=c++17’ or ‘-std=gnu++17’
650 | if constexpr(debug)
| ^~~~~~~~~
In file included from likelihoods.cpp:2:
resamplers.h: In member function ‘void pf::resamplers::sys_hilb_resampler<nparts, dimx, num_hilb_bits, float_t>::resampLogWts(pf::resamplers::sys_hilb_resampler<nparts, dimx, num_hilb_bits, float_t>::arrayVec&, pf::resamplers::sys_hilb_resampler<nparts, dimx, num_hilb_bits, float_t>::arrayFloat&, const usvr&) [with long unsigned int nparts = 500; long unsigned int dimx = 1; long unsigned int num_hilb_bits = 5; float_t = double]’:
resamplers.h:1089:36: warning: ‘idx’ may be used uninitialized in this function [-Wmaybe-uninitialized]
1089 | tmpPartics[i] = sortedParts[idx];
| ~~~~~~~~~~~^
ccache g++ -std=gnu++14 -I"/usr/share/R/include" -DNDEBUG -I'/usr/local/lib/R/site-library/Rcpp/include' -I'/usr/local/lib/R/site-library/RcppEigen/include' -fpic -g -O3 -Wall -pipe -pedantic -Wno-misleading-indentation -Wno-unused -Wno-ignored-attributes -Wno-class-memaccess -c rcppeigen_hello_world.cpp -o rcppeigen_hello_world.o
ccache g++ -std=gnu++14 -Wl,-S -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -flto=auto -Wl,-z,relro -o pfexamplesinr.so RcppExports.o likelihoods.o rcppeigen_hello_world.o -L/usr/lib/R/lib -lR
installing to /tmp/devtools_install_2dc74d5a52ad61/00LOCK-pfexamplesinr/00new/pfexamplesinr/libs
** checking absolute paths in shared objects and dynamic libraries
─ DONE (pfexamplesinr)
edd#rob:~/git/stackoverflow/68985867/pfexamplesinr(master)$
Using this very nice Commandline parser Argo (Header only C++ library) I've encountered a small issue.
See : https://github.com/phforest/Argo
Argo returns : 'Error: Unknown option' when a option in not found, but not when the argument is behind a know argument.
Compiling the code below: (inc is location of the argo header)
c++ test.cpp -I inc --std=c++11
#include <iostream>
int main(int argc, char **argv)
{
argo::Configuration pcnfg;
std::vector<std::string> input_texts;
pcnfg.program.name = { "wow", "EyeOnText WoWoolConsole" };
pcnfg.program.version = { 1, 1, 1 };
argo::Arguments args(pcnfg);
args.add(argo::handler::Option("input-text", "i", input_texts).help("Input text to process."));
const auto result = args.parse(argc, argv);
switch (result.status)
{
case argo::ReturnCode::Error: std::cerr << "Error: " << result.message << std::endl; return 1;
case argo::ReturnCode::SuccessAndAbort: return 0;
default: break;
}
for ( auto const & input : input_texts )
{
std::cout << "- " << input << std::endl;
}
return 0;
}
run:
./a.out --other -i "test"
Error: Unknown option '--other'
Which is ok
run:
./a.out -i "test" --other
- test
- --other
--other should not be in the input list.
(Disclaimer: I'm the developer of the library)
I think this is solved in more recent versions. At least, using the provided code, I get the expected output (twice an 'Unknown option' error). If it's not solved, we can take it up using the bug tracker at https://gitlab.com/dgrine/Argo/issues
Problem background
After upgrading to macos-mojave I don't seem to be able to compile a simple Rcpp function that would use // [[Rcpp::plugins(cpp11)]]. I've tried:
Editing Makevars following this answer
Running xcode-select --install following linked discussion on compiling C under macos after upgrade.
Changing includes, string / string.h leads to the same error
Code
The function, I've drafted to generate the error:
#include <Rcpp.h>
#include <string.h> // std::string, std::stod
using namespace Rcpp;
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
NumericVector convertToDouble(Rcpp::StringVector x) {
// Numeirc vector to store results
NumericVector res;
// Double for converted values
double converted_double;
for(Rcpp::StringVector::iterator it = x.begin(); it != x.end(); ++it) {
// Get [] for vector element
int index = std::distance(x.begin(), it);
// Add results to vector
converted_double = std::stod(x[index]);
res.push_back(converted_double);
}
return res;
}
// Source / test
/*** R
Rcpp::sourceCpp(
file = "sample_stod.cpp",
embeddedR = FALSE,
verbose = TRUE,
rebuild = TRUE,
cleanupCacheDir = TRUE,
showOutput = TRUE)
convertToDouble(c("2.3", "34.25a", "abc32def.43", "12", "1.5"))
*/
Errors
>> Rcpp::sourceCpp(
+ file = "sample_stod.cpp",
+ embeddedR = FALSE,
+ verbose = TRUE,
+ rebuild = TRUE,
+ cleanupCacheDir = TRUE,
+ showOutput = TRUE)
Generated extern "C" functions
--------------------------------------------------------
#include <Rcpp.h>
// convertToDouble
NumericVector convertToDouble(Rcpp::StringVector x);
RcppExport SEXP sourceCpp_1_convertToDouble(SEXP xSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< Rcpp::StringVector >::type x(xSEXP);
rcpp_result_gen = Rcpp::wrap(convertToDouble(x));
return rcpp_result_gen;
END_RCPP
}
Generated R functions
-------------------------------------------------------
`.sourceCpp_1_DLLInfo` <- dyn.load('/private/var/folders/7x/kwc1y_l96t55_rwlv35mg8xh0000gn/T/Rtmp2H7VYU/sourceCpp-x86_64-apple-darwin15.6.0-0.12.19/sourcecpp_295d2f3a47a3/sourceCpp_2.so')
convertToDouble <- Rcpp:::sourceCppFunction(function(x) {}, FALSE, `.sourceCpp_1_DLLInfo`, 'sourceCpp_1_convertToDouble')
rm(`.sourceCpp_1_DLLInfo`)
Building shared library
--------------------------------------------------------
DIR: /private/var/folders/7x/kwc1y_l96t55_rwlv35mg8xh0000gn/T/Rtmp2H7VYU/sourceCpp-x86_64-apple-darwin15.6.0-0.12.19/sourcecpp_295d2f3a47a3
/Library/Frameworks/R.framework/Resources/bin/R CMD SHLIB -o 'sourceCpp_2.so' --preclean 'sample_stod.cpp'
clang++ -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I"/Library/Frameworks/R.framework/Versions/3.5/Resources/library/Rcpp/include" -I"/Users/huski/Documents/R Projects/RcppConversion" -I/usr/local/include -fPIC -Wall -g -O2 -c sample_stod.cpp -o sample_stod.o
sample_stod.cpp:17:28: error: no matching function for call to 'stod'
converted_double = std::stod(x[index]);
^~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/string:3910:30: note: candidate function not viable: no known conversion from 'Rcpp::Vector<16, PreserveStorage>::Proxy' (aka 'string_proxy<16, PreserveStorage>') to 'const std::__1::string' (aka 'const basic_string<char, char_traits<char>, allocator<char> >') for 1st argument
_LIBCPP_FUNC_VIS double stod (const string& __str, size_t* __idx = 0);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/string:3930:30: note: candidate function not viable: no known conversion from 'Rcpp::Vector<16, PreserveStorage>::Proxy' (aka 'string_proxy<16, PreserveStorage>') to 'const std::__1::wstring' (aka 'const basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >') for 1st argument
_LIBCPP_FUNC_VIS double stod (const wstring& __str, size_t* __idx = 0);
^
1 error generated.
make: *** [sample_stod.o] Error 1
Error in Rcpp::sourceCpp(file = "sample_stod.cpp", embeddedR = FALSE, :
Error 1 occurred building shared library.
>>
~/.R/Makevars
# Force use of compilers maintained by Homebrew
# Clang and clang++
CC=/usr/local/opt/llvm/bin/clang
CXX=/usr/local/opt/llvm/bin/clang++
CXX1X=clang-omp++
Tried passing CC \ CXX \ CXX1X variables to use compilers installed via Homebrew but does generate a different error message. All compilation attempts fail on
sample_stod.cpp:17:28: error: no matching function for call to 'stod'
Update: can't find stod
g++ --version
g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 10.0.0 (clang-1000.11.45.2)
Target: x86_64-apple-darwin18.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Current ~/.R/Makevars
# Force use of compilers maintained by Homebrew
# Clang and clang++
# CC=/usr/local/opt/llvm/bin/clang
# CXX=/usr/local/opt/llvm/bin/clang++
# CXX1X=clang-omp++
# Fortran
# FC=/usr/local/opt/gcc/bin/gfortran
# F77=/usr/local/opt/gcc/bin/gfortran
# CC=/usr/local/clang4/bin/clang
# CXX=/usr/local/clang4/bin/clang++
# LDFLAGS=-L/usr/local/clang4/lib
# CPPFLAGS="-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include"
CPPFLAGS="-isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include"
So, outside of the initial issue with respect to the compiler shenanigans on macOS (covered here), you have to help out the compiler when converting to a std::string from a single value in Rcpp::StringVector in this case.
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
Rcpp::NumericVector convertToDouble(Rcpp::StringVector x) {
// Numeirc vector to store results
std::vector<double> res;
// Double for converted values
double converted_double;
for(Rcpp::StringVector::iterator it = x.begin(); it != x.end(); ++it) {
// Get [] for vector element
int index = std::distance(x.begin(), it);
// Help the conversion to string
std::string temp = Rcpp::as<std::string>(x[index]);
// Convert
converted_double = std::stod(temp);
// Add to a std vector... Do not use with Rcpp types
res.push_back(converted_double);
}
// Convert and return the Rcpp type as desired.
return Rcpp::wrap(res);
}
Then, we can run:
convertToDouble(c("2.3", "34.25a", "abc32def.43", "12", "1.5"))
# Error in convertToDouble(c("2.3", "34.25a", "abc32def.43", "12", "1.5")) : stod: no conversion
This errors at: abc32def.43
You may need to do additional cleaning of the string prior to trying a conversion...
I wrote an Inventory program for groceries in C++ using Visual Studio 2012 and
everything runs smoothly and as expected. A file is read in as a command line argument and that is used to fill a deque with Grocery objects. A function that I used to check if a Grocery object was expiring soon used time_t and struct tm. When trying to run my program on Unix, I get an error involving fstream
Here are the lines of code where I am getting the errors:
int main (int argc, char** argv) {
deque<Grocery> groceries;
deque<Grocery>::iterator iter;
string filename = "";
if (argc > 1) {
filename = argv[1];
fstream fileData;
fileData.open(filename, ios::in | ios::out); //**error**
//error check
if (!fileData) {
cout << "Error openeing file. Program aborting.\n";
return 1;
}
string name;
string expDate;
string type;
string quantity;
while (!fileData.eof()) {
Grocery temp;
getline (fileData,name,'\t');
temp.setName(name);
getline (fileData,expDate,'\t');
temp.setExpDate(expDate);
getline (fileData,type,'\t');
temp.setType(type);
getline (fileData, quantity,'\n');
temp.setQuantity(atoi (quantity.c_str()));
groceries.push_back(temp);
}
fileData.close();
}
return 0;
}
Errors when trying to run program in Unix
$ make all
g++ -c Grocery.cpp
g++ -c Inventory.cpp
Inventory.cpp: In function âint main(int, char**)â:
Inventory.cpp:24:45: error: no matching function for call to âstd::basic_fstream<char>::open(std::string&, std::_Ios_Openmode)â
fileData.open(filename, ios::in | ios::out);
^
Inventory.cpp:24:45: note: candidate is:
In file included from Inventory.cpp:3:0:
/opt/rh/devtoolset-2/root/usr/include/c++/4.8.1/fstream:886:7: note: void std::basic_fstream<_CharT, _Traits>::open(const char*, std::ios_base::openmode) [with _CharT = char; _Traits = std::char_traits<char>; std::ios_base::openmode = std::_Ios_Openmode]
open(const char* __s,
^
/opt/rh/devtoolset-2/root/usr/include/c++/4.8.1/fstream:886:7: note: no known conversion for argument 1 from âstd::string {aka std::basic_string<char>}â to âconst char*â
make: *** [Inventory.o] Error 1
Makefile
MKFILE = Makefile
#
# Definitions of list of files:
#
HSOURCES = Grocery.h
CSOURCES = Grocery.cpp Inventory.cpp
ETCSRC = README ${MKFILE}
EXECBIN = main
ALLCSRC = ${CSOURCES}
OBJECTS = ${ALLCSRC:.cpp=.o}
ALLSRC = ${ETCSRC} ${HSOURCES} ${CSOURCES}
LISTSRC = ${ALLSRC}
#
# Definitions of the compiler and compilation options:
#
GCC = g++
#
# The first target is always ``all'', and hence the default,
# and builds the executable images
#
all : ${EXECBIN}
#
# Build the executable image from the object files.
#
${EXECBIN} : ${OBJECTS}
${GCC} -o ${EXECBIN} ${OBJECTS}
#
# Build an object file form a C source file.
#
%.o : %.cpp
${GCC} -c $<
#
# Clean and spotless remove generated files.
#
clean :
- rm -rf ${EXECBIN} ${OBJECTS}
FIXED
Answer listed below
Inventory.cpp:24:45: error: no matching function for call to âstd::basic_fstream<char>::open(std::string&, std::_Ios_Openmode)â
fileData.open(filename, ios::in | ios::out);
basic_fstream(const string&, ios_base::openmode) constructor is only available in C++11 mode.
You are compiling your code in C++98 mode. Pass -std=gnu++11 to g++ when compiling.
I think you need a clean build.
Since you have the declarations in header file, and you might have changed the expDate from type tm to tm*.
So this is probably a long shot, but is there any way to run a C or C++ file as a script? I tried:
#!/usr/bin/gcc main.c -o main; ./main
int main(){ return 0; }
But it says:
./main.c:1:2: error: invalid preprocessing directive #!
Short answer:
//usr/bin/clang "$0" && exec ./a.out "$#"
int main(){
return 0;
}
The trick is that your text file must be both valid C/C++ code and shell script. Remember to exit from the shell script before the interpreter reaches the C/C++ code, or invoke exec magic.
Run with chmod +x main.c; ./main.c.
A shebang like #!/usr/bin/tcc -run isn't needed because unix-like systems will already execute the text file within the shell.
(adapted from this comment)
I used it in my C++ script:
//usr/bin/clang++ -O3 -std=c++11 "$0" && ./a.out; exit
#include <iostream>
int main() {
for (auto i: {1, 2, 3})
std::cout << i << std::endl;
return 0;
}
If your compilation line grows too much you can use the preprocessor (adapted from this answer) as this plain old C code shows:
#if 0
clang "$0" && ./a.out
rm -f ./a.out
exit
#endif
int main() {
return 0;
}
Of course you can cache the executable:
#if 0
EXEC=${0%.*}
test -x "$EXEC" || clang "$0" -o "$EXEC"
exec "$EXEC"
#endif
int main() {
return 0;
}
Now, for the truly eccentric Java developer:
/*/../bin/true
CLASS_NAME=$(basename "${0%.*}")
CLASS_PATH="$(dirname "$0")"
javac "$0" && java -cp "${CLASS_PATH}" ${CLASS_NAME}
rm -f "${CLASS_PATH}/${CLASS_NAME}.class"
exit
*/
class Main {
public static void main(String[] args) {
return;
}
}
D programmers simply put a shebang at the beginning of text file without breaking the syntax:
#!/usr/bin/rdmd
void main(){}
See:
https://unix.stackexchange.com/a/373229/23567
https://stackoverflow.com/a/12296348/199332
For C, you may have a look at tcc, the Tiny C Compiler. Running C code as a script is one of its possible uses.
$ cat /usr/local/bin/runc
#!/bin/bash
sed -n '2,$p' "$#" | gcc -o /tmp/a.out -x c++ - && /tmp/a.out
rm -f /tmp/a.out
$ cat main.c
#!/bin/bash /usr/local/bin/runc
#include <stdio.h>
int main() {
printf("hello world!\n");
return 0;
}
$ ./main.c
hello world!
The sed command takes the .c file and strips off the hash-bang line. 2,$p means print lines 2 to end of file; "$#" expands to the command-line arguments to the runc script, i.e. "main.c".
sed's output is piped to gcc. Passing - to gcc tells it to read from stdin, and when you do that you also have to specify the source language with -x since it has no file name to guess from.
Since the shebang line will be passed to the compiler, and # indicates a preprocessor directive, it will choke on a #!.
What you can do is embed the makefile in the .c file (as discussed in this xkcd thread)
#if 0
make $# -f - <<EOF
all: foo
foo.o:
cc -c -o foo.o -DFOO_C $0
bar.o:
cc -c -o bar.o -DBAR_C $0
foo: foo.o bar.o
cc -o foo foo.o bar.o
EOF
exit;
#endif
#ifdef FOO_C
#include <stdlib.h>
extern void bar();
int main(int argc, char* argv[]) {
bar();
return EXIT_SUCCESS;
}
#endif
#ifdef BAR_C
void bar() {
puts("bar!");
}
#endif
The #if 0 #endif pair surrounding the makefile ensure the preprocessor ignores that section of text, and the EOF marker marks where the make command should stop parsing input.
CINT:
CINT is an interpreter for C and C++
code. It is useful e.g. for situations
where rapid development is more
important than execution time. Using
an interpreter the compile and link
cycle is dramatically reduced
facilitating rapid development. CINT
makes C/C++ programming enjoyable even
for part-time programmers.
You might want to checkout ryanmjacobs/c which was designed for this in mind. It acts as a wrapper around your favorite compiler.
#!/usr/bin/c
#include <stdio.h>
int main(void) {
printf("Hello World!\n");
return 0;
}
The nice thing about using c is that you can choose what compiler you want to use, e.g.
$ export CC=clang
$ export CC=gcc
So you get all of your favorite optimizations too! Beat that tcc -run!
You can also add compiler flags to the shebang, as long as they are terminated with the -- characters:
#!/usr/bin/c -Wall -g -lncurses --
#include <ncurses.h>
int main(void) {
initscr();
/* ... */
return 0;
}
c also uses $CFLAGS and $CPPFLAGS if they are set as well.
#!/usr/bin/env sh
tail -n +$(( $LINENO + 1 )) "$0" | cc -xc - && { ./a.out "$#"; e="$?"; rm ./a.out; exit "$e"; }
#include <stdio.h>
int main(int argc, char const* argv[]) {
printf("Hello world!\n");
return 0;
}
This properly forwards the arguments and the exit code too.
Quite a short proposal would exploit:
The current shell script being the default interpreter for unknown types (without a shebang or a recognizable binary header).
The "#" being a comment in shell and "#if 0" disabling code.
#if 0
F="$(dirname $0)/.$(basename $0).bin"
[ ! -f $F -o $F -ot $0 ] && { c++ "$0" -o "$F" || exit 1 ; }
exec "$F" "$#"
#endif
// Here starts my C++ program :)
#include <iostream>
#include <unistd.h>
using namespace std;
int main(int argc, char **argv) {
if (argv[1])
clog << "Hello " << argv[1] << endl;
else
clog << "hello world" << endl;
}
Then you can chmod +x your .cpp files and then ./run.cpp.
You could easily give flags for the compiler.
The binary is cached in the current directory along with the source, and updated when necessary.
The original arguments are passed to the binary: ./run.cpp Hi
It doesn't reuse the a.out, so that you can have multiple binaries in the same folder.
Uses whatever c++ compiler you have in your system.
The binary starts with "." so that it is hidden from the directory listing.
Problems:
What happens on concurrent executions?
Variatn of John Kugelman can be written in this way:
#!/bin/bash
t=`mktemp`
sed '1,/^\/\/code/d' "$0" | g++ -o "$t" -x c++ - && "$t" "$#"
r=$?
rm -f "$t"
exit $r
//code
#include <stdio.h>
int main() {
printf("Hi\n");
return 0;
}
Here's yet another alternative:
#if 0
TMP=$(mktemp -d)
cc -o ${TMP}/a.out ${0} && ${TMP}/a.out ${#:1} ; RV=${?}
rm -rf ${TMP}
exit ${RV}
#endif
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello world\n");
return 0;
}
I know this question is not a recent one, but I decided to throw my answer into the mix anyways.
With Clang and LLVM, there is not any need to write out an intermediate file or call an external helper program/script. (apart from clang/clang++/lli)
You can just pipe the output of clang/clang++ to lli.
#if 0
CXX=clang++
CXXFLAGS="-O2 -Wall -Werror -std=c++17"
CXXARGS="-xc++ -emit-llvm -c -o -"
CXXCMD="$CXX $CXXFLAGS $CXXARGS $0"
LLICMD="lli -force-interpreter -fake-argv0=$0 -"
$CXXCMD | $LLICMD "$#" ; exit $?
#endif
#include <cstdio>
int main (int argc, char **argv) {
printf ("Hello llvm: %d\n", argc);
for (auto i = 0; i < argc; i++) {
printf("%d: %s\n", i, argv[i]);
}
return 3==argc;
}
The above however does not let you use stdin in your c/c++ script.
If bash is your shell, then you can do the following to use stdin:
#if 0
CXX=clang++
CXXFLAGS="-O2 -Wall -Werror -std=c++17"
CXXARGS="-xc++ -emit-llvm -c -o -"
CXXCMD="$CXX $CXXFLAGS $CXXARGS $0"
LLICMD="lli -force-interpreter -fake-argv0=$0"
exec $LLICMD <($CXXCMD) "$#"
#endif
#include <cstdio>
int main (int argc, char **argv) {
printf ("Hello llvm: %d\n", argc);
for (auto i = 0; i < argc; i++) {
printf("%d: %s\n", i, argv[i]);
}
for (int c; EOF != (c=getchar()); putchar(c));
return 3==argc;
}
There are several places that suggest the shebang (#!) should remain but its illegal for the gcc compiler. So several solutions cut it out. In addition it is possible to insert a preprocessor directive that fixes the compiler messages for the case the c code is wrong.
#!/bin/bash
#ifdef 0
xxx=$(mktemp -d)
awk 'BEGIN
{ print "#line 2 \"$0\""; first=1; }
{ if (first) first=0; else print $0 }' $0 |\
g++ -x c++ -o ${xxx} - && ./${xxx} "$#"
rv=$?
\rm ./${xxx}
exit $rv
#endif
#include <iostream>
int main(int argc,char *argv[]) {
std::cout<<"Hello world"<<std::endl;
}
As stated in a previous answer, if you use tcc as your compiler, you can put a shebang #!/usr/bin/tcc -run as the first line of your source file.
However, there is a small problem with that: if you want to compile that same file, gcc will throw an error: invalid preprocessing directive #! (tcc will ignore the shebang and compile just fine).
If you still need to compile with gcc one workaround is to use the tail command to cut off the shebang line from the source file before piping it into gcc:
tail -n+2 helloworld.c | gcc -xc -
Keep in mind that all warnings and/or errors will be off by one line.
You can automate that by creating a bash script that checks whether a file begins with a shebang, something like
if [[ $(head -c2 $1) == '#!' ]]
then
tail -n+2 $1 | gcc -xc -
else
gcc $1
fi
and use that to compile your source instead of directly invoking gcc.
Just wanted to share, thanks to Pedro's explanation on solutions using the #if 0 trick, I have updated my fork on TCC (Sugar C) so that all examples can be called with shebang, finally, with no errors when looking source on the IDE.
Now, code displays beautifully using clangd in VS Code for project sources. Samples first lines look like:
#if 0
/usr/local/bin/sugar `basename $0` $# && exit;
// above is a shebang hack, so you can run: ./args.c <arg 1> <arg 2> <arg N>
#endif
The original intention of this project always has been to use C as if a scripting language using TCC base under the hood, but with a client that prioritizes ram output over file output (without the of -run directive).
You can check out the project at: https://github.com/antonioprates/sugar
I like to use this as the first line at the top of my programs:
For C (technically: gnu C as I've specified it below):
///usr/bin/env ccache gcc -Wall -Wextra -Werror -O3 -std=gnu17 "$0" -o /tmp/a -lm && /tmp/a "$#"; exit
For C++ (technically: gnu++ as I've specified it below):
///usr/bin/env ccache g++ -Wall -Wextra -Werror -O3 -std=gnu++17 "$0" -o /tmp/a -lm && /tmp/a "$#"; exit
ccache helps ensure your compiling is a little more efficient. Install it in Ubuntu with sudo apt update && sudo apt install ccache.
For Go (golang) and some explanations of the lines above, see my other answer here: What's the appropriate Go shebang line?