Can this be made to display the line number of the actual call site, like the macro does ?
#include <iostream>
#include <type_traits>
#include <source_location>
#include <cassert>
using namespace std;
namespace myLib{
template<typename Enumt, typename... Ts> // alert bad calls, throw
constexpr void setValsF(const unsigned line, Ts const&... args){
cout << "line #"<<line<<": illegal call to setVals()\n";
assert(is_enum_v<Enumt>);
}
template<class... Enumt, class = common_type_t<Enumt...> >
requires conjunction_v<is_enum<Enumt>...>
constexpr void setValsF(const unsigned line, Enumt&... vals){
cout << "line #"<<line<<": legal call to setVals()\n";
}
}// myLib
int main(){
enum enumVals : short { a = 0, b, c, count };
// #define setVals(...) myLib::setValsF<enumVals>(__LINE__ __VA_OPT__(,__VA_ARGS__))
constexpr auto setVals = [](auto&&... args) {
myLib::setValsF<enumVals>(source_location::current().line(), args...); };
setVals(a,b); // legal
setVals(b,"text"); // illegal
}
.. keeping a nice simple API ( setVals(a,b)
), that is.
It would work :
- with a defaulted argument to the function template, but for the parameter pack. Couldn't figure a deduction guide in the presence of more than one template parameter.
- or if current() was the default constructor to source_location !
I resorted to runtime handling of bad calls (to certain APIs) as a courtesy to my library users, as my very specific insult is wayyy nicer than the indecipherable blob the compiler vomits.