I have a templated function inside a non-templated class, like so:
class Foo
{
public:
template <class T>
void func(T& val)
{
//do work here
}
}
Then, in main.cpp I'm doing:
Foo a;
std::string val;
a.func<std::string>(val); //this line gives the error
I get an error saying "primary expression expected before '>'". So I do a quick Google search and find that everyone suggests a simple solution:
a.template func<std::string>(val);
Only problem is, I'm still getting the exact same error.
EDIT :
The reason I wasn't giving the full example is because it involves external libraries and lengthy code that obscures the question, but since the simplified code above doesn't cut it. Here's the complete class that I wrote:
class ConfigFileReader
{
public:
ConfigFileReader() { }
ConfigFileReader(const std::string& config_file_path)
{
setConfigFilePath(config_file_path);
}
~ConfigFileReader() { }
void setConfigFilePath(const std::string& config_file_path)
{
try
{
root_node_ = YAML::LoadFile(config_file_path);
}
catch(const YAML::BadFile& file_load_exception)
{
printf("Error opening YAML file. Maybe the file path is incorrect\n%s", file_load_exception.msg.c_str());
}
}
template<class T>
bool getParam(const std::string& param_key, T& param_value)
{
if (root_node_.IsNull() || !root_node_.IsDefined())
{
printf("Root node is undefined or not set");
return false;
}
YAML::Node node = YAML::Clone(root_node_);
std::vector<std::string> split_name;
boost::split(split_name, param_key, boost::is_any_of("/"));
for(const std::string& str: split_name)
{
if (!node.IsMap())
{
std::cout << "Parameter was not found (Node is null)." << str << std::endl; //replace with printf
return false;
}
node = node[str];
}
if (node.IsNull() || !node.IsDefined())
{
std::cout << "Parameter was not found (Node is null/undefined)." << std::endl;
return false;
}
try
{
param_value = node.as<T>();
return true;
}
catch (const YAML::TypedBadConversion<T>& type_conversion_exception)
{
std::cout << "Error converting param value into specified data type" << std::endl;
std::cout << type_conversion_exception.msg << std::endl;
}
return false;
}
private:
YAML::Node root_node_;
};
Then, in a separate cpp file is the main function
int main(int argc, char** argv)
{
if (argc != 2)
{
printf("Incorrect number of arguments given");
return EXIT_FAILURE;
}
printf("Config file path: %s", argv[1]);
ConfigFileReader config_file_reader(std::string(argv[1]));
std::string param_out;
bool success = config_file_reader.template getParam<std::string>("controller/filepath", param_out); //<-- ERROR HERE
return EXIT_SUCCESS;
}
Compiler: gcc 4.8.4, and c++11 flag set when compiling.
EDIT 2:
Added string argument constructor to the code.
Your problem is that this:
ConfigFileReader config_file_reader(std::string(argv[1]));
Is interpreted as a forward declaration for a function named config_file_reader that accepts a pointer to a string. See the error message:
ConfigFileReader(std::__cxx11::string*) {aka ConfigFileReader(std::__cxx11::basic_string*)}'
This is because you've encountered The most vexing parse
Use ConfigFileReader config_file_reader(std::string{argv[1]}); to better disambiguate for the compiler that you are intending to construct an object. Then the compiler will start complaining that you're missing a constructor that accepts a string!
You do have a default constructor, so when we use that:
ConfigFileReader config_file_reader;
It works without issue.
So:
define a constructor for ConfigFileReader that accepts a string , then
Call it in such a way that the code is unambiguous
Demo
It's even simpler:
Foo a;
std::string val;
a.func(val); // The compiler assumes T = std::string
Related
I have currently a function
int myfun(const int a) {
...
return rval;
}
that performs several actions.
I mean to adapt it to write debug information on its behaviour or not according to some parameter that I can pass.
In the cases I want to write that info, I also want to pass the ofstream to use.
And I want applications that were using myfun to still work with no modifications.
So I would ideally change to
int myfun(const int a, ofstream & ofs) {
...
if (!(ofs == NULL)) {
ofs << ...
}
...
if (!(ofs == NULL)) {
ofs << ...
}
return rval;
}
with a default value similar to &ofs=NULL. I know NULL is not appropriate.
What is an appropriate way of handling this?
Note 1:
I could pass an optional parameter with the output file name, but that is less flexible.
Note 2:
I could also change to
int myfun(const int a, const bool debug_info, ofstream & ofs) {
...
if (debug_info) {
ofs << ...
}
with a default value debug_info=false.
I guess this still requires a default value for ofs as above.
Note 3:
The accepted answer in Default ofstream class argument in function proposes an overload without the ofs parameter.
In my case that may not work, as I mean to not write anything when "ofs=NULL".
Note 4:
This other answer apparently works, but it seems somewhat contrived to me, and I am not sure it provides all the same functionality as with passing an ofs.
Related:
Is there a null std::ostream implementation in C++ or libraries?
I want applications that were using myfun to still work with no modifications.
If so, use an ofs with default nullptr
int myfun(const int a, ofstream *ofs = nullptr)
{
if (ofs != nullptr)
{
// (*ofs) << ... ;
}
// ...
}
You can't use a reference parameter ofstream& ofs for such function because a reference cannot be null.
Make an abstract Logger class. It has a method for logging a message. In derived classes you can add logging to file (ofstream) or simply do nothing. You can use any logger, the implementation of myfun() stays the same.
#include <fstream>
class Logger {
public:
virtual void log(const char*) = 0;
};
class NullLogger: public Logger {
public:
void log(const char*) override {};
};
class FileLogger: public Logger {
public:
FileLogger(std::ofstream& s): ofs(s){}
void log(const char* msg) override {
ofs << msg;
}
private:
std::ofstream& ofs;
};
static NullLogger defaultLogger;
int myfun(const int a, Logger& logger=defaultLogger)
{
logger.log("hello");
// ...
logger.log("asdf");
}
int main(){
std::ofstream ofs;
FileLogger fileLogger(ofs);
NullLogger nullLogger;
myfun(10,fileLogger); // logs to file
myfun(10,nullLogger); // logs nothing
myfun(10); // also logs nothing
return 0;
}
In C++17 there is a solution involving std::optional but since it requires default constructible types, std::reference_wrapper has to be used too.
#include <fstream>
#include <optional>
#include <functional>
int myfun(const int a, std::optional<std::reference_wrapper<std::ofstream>> ofs)
{
if (ofs) {
ofs->get() << "...";
return 1;
}
else{
return 0;
}
}
#include <iostream>
int main(){
std::ofstream file;
//Calling is quite nice.
std::cout<<myfun(10,{file})<<'\n'; //Prints 1
std::cout<<myfun(10,{})<<'\n'; //Prints 0
}
The downside of this solution, although idiomatic, is being verbose and heavy on the syntax in some cases.
I have encountered a problem while dealing with template specialization. I'd like to have method that has an enum as argument and depending on it call specialized templated method. Heres the presentation:
#include <iostream>
enum EnumType
{
ENUM1,
ENUM2,
ENUM3
};
class Test
{
public:
template <EnumType enumType>
bool enumFunc(const int i )
{
std::cout << i << " default\n";
return false;
}
bool func(const EnumType e);
};
template<>
bool Test::enumFunc<ENUM2>(const int i )
{
std::cout << i << " ENUM2 \n";
return true;
}
//... and other specializations
bool Test::func(const EnumType e)
{
// this one works
// return enumFunc<ENUM2>(3);
// but this:
// error: no matching function for call to 'Test::enumFunc<e>(int)
return enumFunc<e>(3);
}
int main()
{
Test a;
a.enumFunc<ENUM2>(2); // works
a.func(ENUM2); // doesnt even get there due to previous error
return 0;
}
As noted in the comments, the value of the argument e is only known at run time, so you cannot use template specializations (which are evaluated at compile time). The following is, perhaps, the simplest implementation of your Test::func():
bool Test::func(const EnumType e)
{
switch (e) {
case ENUM1: return enumFunc<ENUM1>(3);
case ENUM2: return enumFunc<ENUM2>(3);
case ENUM3: return enumFunc<ENUM3>(3);
}
return false; // Handle error condition(s)
}
I have a ResourceManager which takes in classes of type Resource. Resource is a parent class of other classes such as ShaderProgram, Texture, Mesh and even Camera who are completely unrelated to one another.
Suffice it to say, the ResourceManager works. But there is one thing that is very tedious and annoying, and that's when I retrieve the objects from the ResourceManager. Here is the problem:
In order to get an object from ResourceManager you call either of these functions:
static Resource* get(int id);
static Resource* get(const std::string &name);
The first function checks one std::unordered_map by an integer id; whereas the second function checks another std::unordered_map by the name that is manually given by the client. I have two versions of these functions for flexibility sakes because there are times where we don't care what the object contained within ResourceManager is (like Mesh) and there are times where we do care about what it is (like Camera or ShaderProgram) because we may want to retrieve the said objects by name rather than id.
Either way, both functions return a pointer to a Resource. When you call the function, it's as easy as something like:
rm::get("skyboxShader");
Where rm is just a typedef of ResourceManager since the class is static (all members/functions are static). The problem though is that the rm::get(..) function returns a Resource*, and not the child class that was added to the ResourceManager to begin with. So, in order to solve this problem I have to do a manual type conversion so that I can get ShaderProgram* instead of Resource*. I do it like this:
auto s = static_cast<ShaderProgram*>(rm::get(name));
So, everytime I want to access a Resource I have to insert the type I want to actually get into the static_cast. This is problematic insofar that everytime someone needs to access a Resource they have to type convert it. So, naturally I created a function, and being that ShaderProgram is the subject here, thus:
ShaderProgram* Renderer::program(const std::string &name)
{
auto s = static_cast<ShaderProgram*>(rm::get(name));
return s;
}
This function is static, and ResourceManager is a static class so the two go well hand-in-hand. This is a nice helper function and it works effectively and my program renders the result just fine. The problem is what I have to do when I'm dealing with other Resources; that means for every Resource that exists, there has to be a type-conversion function to accommodate it. Now THAT is annoying. Isn't there a way I can write a generic type-conversion function something like this?
auto Renderer::getResource(classTypeYouWant T, const std::string &name)
{
auto s = static_cast<T*>(rm::get(name));
return s;
}
Here, the auto keyword causes the function to derive which type it's supposed to be dealing with and return the result accordingly. My first guess is that I might have to use templates; but the problem with templates is that I can't limit which types get inserted into the function, and I really REALLY don't want floating-point id numbers, char ids, let alone custom-defined ids. It's either string (might change to const char* tbh) or ints or else.
How can I create a generic conversion function like the one described above?
Have you looked at using dynamic_cast? If the conversion fails with dynamic_cast the the pointer will be set to nullptr. So you could either write overloads for each type or you could write a template function where you pass the the type you want to convert to as well as the string or id and if the conversion succeeds or fails return true or false.
template<typename T>
bool Renderer::getResource(T*& type, const std::string &name)
{
type = dynamic_cast<decltype(std::remove_reference<decltype(T)>::type)>(rm::get(name));
if (type == nullptr)
return false;
return true;
}
OK, I did not like the idea of a typeless storage, but maybe you find that basic program as a start point. There are a lot of things which must be beautified, but some work must remain :-)
Again: It is a design failure to solve something in that way!
In addition to your example code this solution provides a minimum of safety while checking for the stored type while recall the element. But this solution needs rtti an this is not available on all platforms.
#include <map>
#include <iostream>
#include <typeinfo>
class ResourcePointerStorage
{
private:
std::map< const std::string, std::pair<void*, const std::type_info*>> storage;
public:
bool Get(const std::string& id, std::pair<void*, const std::type_info*>& ptr )
{
auto it= storage.find( id );
if ( it==storage.end() ) return false;
ptr= it->second;
return true;
}
bool Put( const std::string& id, void* ptr, const std::type_info* ti)
{
storage[id]=make_pair(ptr, ti);
}
};
template < typename T>
bool Get(ResourcePointerStorage& rm, const std::string& id, T** ptr)
{
std::pair<void*, const std::type_info*> p;
if ( rm.Get( id,p ))
{
if ( *p.second != typeid(T)) { return false; }
*ptr= static_cast<T*>(p.first);
return true;
}
else
{
return 0;
}
}
template < typename T>
void Put( ResourcePointerStorage& rm, const std::string& id, T *ptr)
{
rm.Put( id, ptr, &typeid(T) );
}
class Car
{
private:
int i;
public:
Car(int _i):i(_i){}
void Print() { std::cout << "A car " << i << std::endl; }
};
class Animal
{
private:
double d;
public:
Animal( double _d):d(_d) {}
void Show() { std::cout << "An animal " << d << std::endl; }
};
int main()
{
ResourcePointerStorage store;
Put( store, "A1", new Animal(1.1) );
Put( store, "A2", new Animal(2.2) );
Put( store, "C1", new Car(3) );
Animal *an;
Car *car;
if ( Get(store, "A1", &an)) { an->Show(); } else { std::cout << "Error" << std::endl; }
if ( Get(store, "A2", &an)) { an->Show(); } else { std::cout << "Error" << std::endl; }
if ( Get(store, "C1", &car)) { car->Print(); } else { std::cout << "Error" << std::endl; }
// not stored object
if ( Get(store, "XX", &an)) { } else { std::cout << "Expected false condition" << std::endl; }
// false type
if ( Get(store, "A1", &car)) { } else { std::cout << "Expected false condition" << std::endl; }
};
I've found the solution to my question. I created a macro:
#define convert(type, func) dynamic_cast<type>(func)
Extremely generic and code-neutral which allows types to be dynamic_casted from the return type of the function. It also allows for doing checks:
if (!convert(ShaderProgram*, rm::get("skyboxShader")))
cerr << "Conversion unsuccessful!" << endl;
else cout << "Conversion successful!" << endl;
I hope my solution will help people who search for questions similar of this kind. Thanks all!
I've been thinking of a solution to validate the set of parameters a function/method receives using an object oriented approach. For example, in the following snippet the parameters are checked "manually" before being used.
InstallData::InstallData(std::string appPath, std::string appName,
std::string errMsg) {
if(appPath.empty()) {
#ifndef NDEBUG
std::cout << "Path not specified" << std::endl;
#endif
}
if(appName.empty()) {
#ifndef NDEBUG
std::cout << "Application name not specified" << std::endl;
std::cout << "Defaulting to AppName" << std::endl;
this->appName = "AppName";
#endif
}
if(errMsg.empty()) {
#ifndef NDEBUG
std::cout << "Error message not specified" << std::endl;
std::cout << "Defaulting to Error" << std::endl;
this->errMsg = "Error";
#endif
}
// ... further initialization beyond this point ...
}
As the number of parameters increases so does the size of the validation code. I've thought of a basic approach of checking parameters(strings and pointers) as whether they are either empty or null(the aim is to make the code providing functionality more readable).
class Validator {
public:
bool validateStrs(std::vector<std::string> strings, std::vector<std::string> messages, bool quiet);
bool validateStr(std::string str, std::string message, bool quiet);
bool validatePtrs(std::vector<void*> ptrs, std::vector<std::string> messages, bool quiet);
bool validatePtr(void* ptr, std::string message, bool quiet);
};
The validation methods validateStrs and validatePtrs check whether each element of the first array is empty or null and display a message from the second array(there is a one to one relationship between the elements of the first array and the second) if the quiet flag is not set.
In my implementation this looks like:
InstallData::InstallData(std::string appPath, std::string appName,
std::string errMsg, std::string errTitle) {
// Initialize string container
std::vector<std::string> strings;
strings.push_back(appPath);
strings.push_back(appName);
strings.push_back(errMsg);
strings.push_back(errTitle);
// Initialize name container
std::vector<std::string> names;
names.push_back("ApplicationPath");
names.push_back("ApplicationName");
names.push_back("ErrorMessage");
names.push_back("ErrorTitle");
boost::shared_ptr<Validator> valid(new Validator());
bool result = true;
#ifndef NDEBUG
result = valid->validateStrs(strings, names, false);
#else
result = valid->validateStrs(strings, names, true);
#endif
if(result){
this->appPath = appPath;
this->appName = appName;
this->errMsg = errMsg;
this->errTitle = errTitle;
} else {
std::exit(0);
}
}
The messages can also be placed in a separate file thus making the method body cleaner.
Numeric value range checkers can also be implemented similarly. This approach, however, doesn't consider dependencies between parameters.
Is there a more elegant solution of implementing a parameter validation mechanism, possibly using templates?
A more elegant way is not to use standard types for parameters but to define specific classes that check parameters on construction. Something like
class InvalidAppPath {};
class AppPath {
public:
AppPath(const std::string & appPath) : path(appPath) {
if ( appPath.empty() ) throw InvalidAppPath();
}
operator std::string() { return path; }
private:
std::string path;
};
This would also make it easier to ensure that an AppPath is checked for validity only on construction and possibly on modification.
These slides from a presentation by Ric Parkin at the 2007 ACCU Conference explore the idea in greater detail.
Perhaps you would find it easier to leverage function name overloading and variadic templates. You can group the parameter information you want to validate along with the corrective action together in a std::tuple. I implemented a small demo of this idea on IDEONE.
bool validate (std::string s) { return !s.empty(); }
bool validate (const void *p) { return p; }
template <typename Tuple>
bool validate (Tuple param) {
if (validate(std::get<0>(param))) return true;
#ifndef NDEBUG
std::cout << "Invalid: " << std::get<1>(param) << std::endl;
std::get<2>(param)();
#endif
return false;
}
bool validate () { return true; }
template <typename T, typename... Params>
bool validate (T param, Params... params) {
return validate(param) & validate(params...);
}
Then, you could use it like:
bool result
= validate(
std::make_tuple(appPath, "ApplicationPath",
[&](){ appPath = "defaultPath"; }),
std::make_tuple(appName, "ApplicationName",
[&](){ appName = "defaultName"; })
//...
);
I have recently started using boost::exception. Now I would like to use boost::errinfo_nested_exception to print information about the cause of the error. The problem is I can't figure out how to get information from the cause. I have tried the following with no success:
#include <iostream>
#include <boost/exception/all.hpp>
struct myex : public virtual boost::exception {};
int main()
{
myex cause;
cause << boost::errinfo_file_name("causefile.cpp");
try {
myex ex;
ex << boost::errinfo_nested_exception(boost::copy_exception(cause));
throw ex;
}
catch (myex& e) {
// Here I would like to extract file name from cause and print
// it in a nice way, but I cant figure out what to do with a
// boost::exception_ptr.
const boost::exception_ptr* c =
boost::get_error_info<boost::errinfo_nested_exception>(e);
// I cant do this:
// const std::string* file = boost::get_error_info<boost::errinfo_file_name>(*c);
// Nor this:
// const std::string* file = boost::get_error_info<boost::errinfo_file_name>(**c);
// This works fine and the nested exception is there, but that's not what I want.
std::cout << boost::diagnostic_information(e) << std::endl;
}
return 0;
}
You need to rethrow the nested exception and examine that:
const boost::exception_ptr* c =
boost::get_error_info<boost::errinfo_nested_exception>(e);
if(c) try {
boost::rethrow_exception(*c);
} catch(boost::exception const& e) { // or a type derived from it
const std::string* file = boost::get_error_info<boost::errinfo_file_name>(e);
// ...
} catch(...) {
// presumably you don't want the exception to escape if it is
// not derived from boost::exception
}
I personally use a get_error_info wrapper that returns the result of boost::get_error_info<some_error_info>(e), or if nothing is found the result of get_error_info<some_error_info>(nested) (recursive call here) or 0 if there is no nested exception (or it is not error_info-enabled).
Alternatively/as a complement, you can factor the checking code above (the different catch clauses) in a function:
std::string const* // or return a tuple of what you examined etc.
examine_exception()
{
try {
throw; // precondition: an exception is active
} catch(boost::exception const& e) {
// as above
return ...;
}
}
boost::diagnostic_information is the correct way to get a description afaik.
But you could also overload to_string for boost::error_info(T):
http://svn.boost.org/svn/boost/trunk/boost/exception/errinfo_errno.hpp