I'm writing a helper function for logging purposes: it collects call-site information while also creating a Error
-typed object.
template<typename ErrorTy, typename... ArgTys>
std::unique_ptr<Error> makeError(const char* fileName = __builtin_FILE(),
int lineNum = __builtin_LINE(),
const char* funcName = __builtin_FUNCTION(), ArgTys &&... args) {
return std::make_unique<ContextualError<ErrorTy>>(fileName, lineNum, funcName,
std::forward<ArgTys>(args)...);
}
// ...
template<typename ErrorTy>
struct ContextualError : ErrorTy {
template<typename... ArgTys>
ContextualError(std::string_view fileName, int lineNum,
std::string_view funcName, ArgTys &&... args) :
fileName_(fileName), lineNum_(lineNum), funcName_(funcName),
ErrorTy(std::forward<ArgTys>(args)...) {}
// ...
};
As the actual Error
classes can have arbitrary constructors, I was hoping to get makeError
and the ContextualError
constructor to perfectly forward everything. Unfortunately, calling makeError
like this will try to fill the first three optional arguments, rather than skipping them and filling the parameter pack:
auto err = makeError<FileError>("foo.exe", "Invalid header");
// error: no matching function for call to 'makeError'
// note: candidate function template not viable: no known conversion
// from 'const char [15]' to 'int' for 2nd argument
Moving the parameter pack to the front of the arguments list doesn't seem to fix this either. Is there any way to achieve this perfect forwarding while keeping the optional arguments?
Minimum reproducible example on Godbolt
Aucun commentaire:
Enregistrer un commentaire