210 template<
typename... ARGS>
requires (is_arg_v<ARGS> && ...)
struct args;
216 template<
typename T>
struct is_args_impl : std::false_type {};
217 template<
typename... Ts>
struct is_args_impl<args<Ts...>> : std::true_type {};
221 using is_args = detail::is_args_impl<std::decay_t<T>>;
231 template<
typename... Ts>
struct add_args_impl;
232 template<
typename... Ts>
requires (is_arg_v<Ts> && ...)
struct add_args_impl <Ts...> {
using type =
args<Ts...>; };
233 template<
typename T>
requires is_args_v<T>
struct add_args_impl<T> {
using type = T; };
236 template<
typename... Ts>
239 template<
typename... Ts>
246 template<
typename... ARGS>
requires (is_arg_v<ARGS> && ...)
259 template<
typename... Ts>
262 template<
typename... Ts>
282 static constexpr size_t size =
sizeof...(ARGS);
285 template<
size_t IDX>
using type = std::tuple_element_t<IDX, std::tuple<ARGS...>>;
291 inline constexpr auto values(
void)
const {
return _value( std::make_index_sequence<
sizeof...(ARGS)>{} ); }
297 template<
size_t IDX>
inline constexpr decltype(
auto)
get(
void) {
return std::get<IDX>(
_values); }
298 template<
size_t IDX>
inline constexpr decltype(
auto)
get(
void)
const {
return std::get<IDX>(
_values); }
301 template<
size_t IDX>
inline constexpr decltype(
auto)
value(
void) {
return get<IDX>().value(); }
302 template<
size_t IDX>
inline constexpr decltype(
auto)
value(
void)
const {
return get<IDX>().value(); }
305 template<
string_literal Name,
typename T=
void,
typename D=
void>
308 const size_t idx = _lookup<Name>();
313 template<
string_literal Name,
typename T=
void,
typename D=
void>
316 const size_t idx = _lookup<Name>();
322 template<
string_literal Name,
typename T=
void,
typename D=
void>
inline constexpr decltype(
auto)
value(
arg<T,Name,D> =
arg<T,Name,D>{}) {
return get<Name>().value(); }
323 template<
string_literal Name,
typename T=
void,
typename D=
void>
inline constexpr decltype(
auto)
value(
arg<T,Name,D> =
arg<T,Name,D>{})
const {
return get<Name>().value(); }
333 template<
string_literal Name,
typename T=
void,
typename D=
void>
336 size_t result =
size;
341 if constexpr (type<idx>::name == Name) result = idx;
344 if constexpr (to_string_literal<idx>() == Name) result = idx;
358 template<
typename TUP,
size_t... IDX>
359 static inline constexpr decltype(
auto)
_retrieve_args(TUP&& src, std::index_sequence<IDX...>)
361 return std::make_tuple( _retrieve_arg<IDX>(std::forward<TUP>(src))... );
371 template<
size_t IDX,
typename TUP>
377 constexpr size_t idx = _find_arg_index<IDX, TUP>();
380 if constexpr (idx != std::tuple_size_v<TUP>)
382 decltype(
auto)
arg = std::get<idx>( std::forward<TUP>(src) );
383 return arg_type(std::forward<
decltype(
arg)>(
arg));
387 else if constexpr (std::is_constructible_v<arg_type>)
return arg_type{};
390 else static_assert(dependent_false_v<TUP>,
BBM_NO_MATCH);
399 template<
typename TUP>
402 bool compatible =
true;
403 bool arg_used[ std::tuple_size_v<TUP> ];
404 std::fill_n(arg_used, std::tuple_size_v<TUP>,
false);
409 const size_t argIdx = _find_arg_index<idx, TUP>();
412 if constexpr (argIdx >= std::tuple_size_v<TUP>)
414 if constexpr (!std::is_constructible_v<type<idx>>) compatible =
false;
418 else if(arg_used[ argIdx ]) compatible =
false;
421 else arg_used[ argIdx ] =
true;
425 return compatible && std::all_of(arg_used, arg_used + std::tuple_size_v<TUP>, [](
bool b) {
return b; });
436 template<
typename TUP>
439 bool compatible =
true;
440 bool defaulted =
false;
441 bool arg_used[ std::tuple_size_v<TUP> ];
442 std::fill_n(arg_used, std::tuple_size_v<TUP>,
false);
446 const size_t found_idx = _find_arg_index<idx, TUP>();
449 if constexpr (found_idx != std::tuple_size_v<TUP>)
451 arg_used[ found_idx ] =
true;
452 if(defaulted) compatible =
false;
453 if constexpr (found_idx != idx) compatible =
false;
454 if constexpr (is_arg_v< std::tuple_element_t<found_idx, TUP> >) compatible =
false;
461 if constexpr (!std::is_constructible_v<type<idx>>) compatible =
false;
466 return compatible && std::all_of(arg_used, arg_used + std::tuple_size_v<TUP>, [](
bool b) {
return b; });
483 template<
size_t IDX,
typename TUP>
486 size_t result = std::tuple_size_v<TUP>;
490 if constexpr (!arg_type::name.empty)
492 CONSTFOR(tupIdx, std::tuple_size_v<TUP>,
494 using tup_type = std::tuple_element_t<tupIdx, TUP>;
496 if constexpr (is_arg_v<tup_type>)
497 if constexpr (std::decay_t<tup_type>::name == arg_type::name)
498 if constexpr (std::convertible_to<typename std::decay_t<tup_type>::type, arg_type>) result = tupIdx;
502 if(result != std::tuple_size_v<TUP>)
return result;
506 CONSTFOR(tupIdx, std::tuple_size_v<TUP>,
508 using tup_type = std::tuple_element_t<tupIdx, TUP>;
509 if constexpr (is_arg_v<tup_type>)
510 if constexpr (std::decay_t<tup_type>::name == to_string_literal<IDX>())
511 if constexpr (std::convertible_to<typename std::decay_t<tup_type>::type, arg_type>) result = tupIdx;
515 if(result != std::tuple_size_v<TUP>)
return result;
518 if constexpr (IDX < std::tuple_size_v<TUP>)
520 using tup_type = std::tuple_element_t<IDX, TUP>;
523 if constexpr (!is_arg_v<tup_type>)
525 if constexpr (std::convertible_to<tup_type, arg_type>)
return IDX;
529 else if constexpr (std::decay_t<tup_type>::name.empty)
530 if constexpr (std::convertible_to<
typename std::decay_t<tup_type>::type, arg_type>)
return IDX;
534 size_t arg_count = 0;
537 arg_count += std::is_same_v<std::decay_t<typename arg_type::type>, std::decay_t<typename ARG::type>>;
542 size_t tup_count = 0;
543 size_t found_idx = std::tuple_size_v<TUP>;
544 CONSTFOR(tupIdx, std::tuple_size_v<TUP>,
546 using tup_type = std::tuple_element_t<tupIdx, TUP>;
547 if constexpr (std::is_same_v<std::decay_t<tup_type>, std::decay_t<typename arg_type::type>>)
555 if(tup_count == 1 && found_idx < std::tuple_size_v<TUP>)
return found_idx;
568 template<
size_t... IDX>
569 inline constexpr auto _value(std::index_sequence<IDX...>)
const
571 return make_named<name<IDX>...>(std::forward_as_tuple( value<IDX>()... ));
585 template<
typename... ARGS>
requires (bbm::is_arg_v<ARGS> && ...)
590 if constexpr (idx > 0) s <<
", ";
591 s <<
args.template get<idx>();
605#define BBM_IMPORT_ARGS(ARGS, ...) \
606 auto& _bbm_import_args = ARGS; \
607 BBM_FOREACH( _BBM_IMPORT_ARG_HELPER, __VA_ARGS__ ) \
610#define _BBM_IMPORT_ARG_HELPER(ARGNAME) BBM_IMPORT_ARG(_bbm_import_args, ARGNAME)
618#define BBM_IMPORT_ARG(ARGS, ARGNAME) \
619 decltype(auto) ARGNAME = ARGS.value(#ARGNAME ## _arg); \
631#define _BBM_FORWARD_ARGS(NAME, CTE, ...) \
632 template<typename... _ArgTs> requires \
633 (bbm::add_args_t<__VA_ARGS__>::template is_compatible<_ArgTs...> && \
634 !(bbm::is_args_v<_ArgTs> && ...)) \
635 inline constexpr auto NAME(_ArgTs&&... t) CTE \
637 return NAME(bbm::add_args_t<__VA_ARGS__>{std::forward<_ArgTs>(t)...}); \
641#define BBM_FORWARD_ARGS(NAME, ...) BBM_CALL(_BBM_FORWARD_ARGS, NAME, , __VA_ARGS__)
644#define BBM_FORWARD_ARGS_CONST(NAME, ...) BBM_CALL(_BBM_FORWARD_ARGS, NAME, const, __VA_ARGS__)
656#define _BBM_FORWARD_CPP_ARGS(NAME, CTE, ...) \
657 template<typename... _ArgTs> requires \
658 (!bbm::add_args_t<__VA_ARGS__>::template is_cpp_compatible<_ArgTs...> && \
659 bbm::add_args_t<__VA_ARGS__>::template is_compatible<_ArgTs...> && \
660 !(bbm::is_args_v<_ArgTs> && ...)) \
661 inline constexpr auto NAME(_ArgTs&&... t) CTE \
663 auto launcher = [&]<typename ARGS, size_t... IDX>(ARGS&& args, std::index_sequence<IDX...>) { return NAME(args.template value<IDX>()...); }; \
664 return launcher(bbm::add_args_t<__VA_ARGS__>{std::forward<_ArgTs>(t)...}, std::make_index_sequence<bbm::add_args_t<__VA_ARGS__>::size>{}); \
668#define BBM_FORWARD_CPP_ARGS(NAME, ...) BBM_CALL(_BBM_FORWARD_CPP_ARGS, NAME, , __VA_ARGS__)
671#define BBM_FORWARD_CPP_ARGS_CONST(NAME, ...) BBM_CALL(_BBM_FORWARD_CPP_ARGS, NAME, const, __VA_ARGS__)
686#define _BBM_CONSTRUCTOR_FORWARD_ARGS(NAME, ...) \
687 template<typename... _ArgTs> requires \
688 (bbm::add_args_t<__VA_ARGS__>::template is_compatible<_ArgTs...> && \
689 !(bbm::is_args_v<_ArgTs> && ...) && \
690 !(sizeof...(_ArgTs) == 1 && (std::is_same_v<NAME, std::decay_t<_ArgTs>> && ...))) \
691 inline constexpr NAME(_ArgTs&&... t) \
692 : NAME(bbm::add_args_t<__VA_ARGS__>{std::forward<_ArgTs>(t)...}) {}\
694 template<typename=void> requires bbm::add_args_t<__VA_ARGS__>::template is_compatible<> \
695 inline constexpr NAME(void) : NAME( bbm::make_from<bbm::add_args_t<__VA_ARGS__>>()) {} \
698#define BBM_CONSTRUCTOR_FORWARD_ARGS(...) BBM_CALL(_BBM_CONSTRUCTOR_FORWARD_ARGS, __VA_ARGS__)
714#define _BBM_CONSTRUCTOR_FORWARD_CPP_ARGS(NAME, ...) \
715 template<size_t... _ArgIdx> requires (sizeof...(_ArgIdx) == bbm::add_args_t<__VA_ARGS__>::size) \
716 inline constexpr NAME(bbm::add_args_t<__VA_ARGS__>&& args, std::index_sequence<_ArgIdx...>) \
717 : NAME(args.template value<_ArgIdx>()...) {} \
719 template<typename... _ArgTs> requires \
720 (!bbm::add_args_t<__VA_ARGS__>::template is_cpp_compatible<_ArgTs...> && \
721 bbm::add_args_t<__VA_ARGS__>::template is_compatible<_ArgTs...> && \
722 !(bbm::is_args_v<_ArgTs> && ...) && \
723 !(sizeof...(_ArgTs) == 1 && (std::is_same_v<NAME, std::decay_t<_ArgTs>> && ...))) \
724 inline constexpr NAME(_ArgTs&&... t) \
725 : NAME(bbm::add_args_t<__VA_ARGS__>{std::forward<_ArgTs>(t)...}, std::make_index_sequence<bbm::args<__VA_ARGS__>::size>{}) {} \
728#define BBM_CONSTRUCTOR_FORWARD_CPP_ARGS(...) BBM_CALL(_BBM_CONSTRUCTOR_FORWARD_CPP_ARGS, __VA_ARGS__)
Structure to store an argument, with possibly a type, name and default value. Refer to args....
#define CONSTFOR(IDX, NUMITR,...)
HELPER MACRO.
Definition: constfor.h:63
Compile-time for each loop.
#define CONSTFOREACH(ITR_TYPE, TYPE_LIST,...)
HELPER MACRO.
Definition: constforeach.h:53
Predefined exceptions for common errors.
#define BBM_NO_MATCH
Definition: error.h:51
concept to check if a type has a valid string_converter.
Tools for making an object:
Definition: aggregatebsdf.h:29
detail::is_args_impl< std::decay_t< T > > is_args
Definition: args.h:221
std::ostream & operator<<(std::ostream &s, const BSDF &bsdf)
Definition: bsdf_base.h:138
detail::add_args_impl< Ts... > add_args
Definition: args.h:237
typename add_args< Ts... >::type add_args_t
Definition: args.h:240
constexpr bool is_args_v
Definition: args.h:224
Forward declaration of bbm::arg.
Definition: arg.h:27
Forward declaration.
Definition: args.h:248
static constexpr bool _is_compatible_fwd(void)
Definition: args.h:251
constexpr args(args< Ts... > &&arg)
Copy constructor for compatible arg_lists.
Definition: args.h:272
constexpr auto _value(std::index_sequence< IDX... >) const
Return the value of all arguments.
Definition: args.h:569
std::tuple_element_t< IDX, std::tuple< ARGS... > > type
type of the IDX argument
Definition: args.h:285
constexpr decltype(auto) get(void)
Get the IDX-th argument (bbm::arg type)
Definition: args.h:297
constexpr decltype(auto) value(void)
Get the value of the IDX-th argument.
Definition: args.h:301
static constexpr size_t _find_arg_index(void)
Find the element in a tuple of argument values that best matches the IDX-th 'ARGS'.
Definition: args.h:484
std::tuple< ARGS... > _values
Definition: args.h:578
static constexpr bool _is_compatible(void)
Checks if a tuple of arguments is compatible with ARGS.
Definition: args.h:400
constexpr decltype(auto) value(arg< T, Name, D >=arg< T, Name, D >{})
Get the value of the argument with a given name.
Definition: args.h:322
constexpr decltype(auto) value(void) const
Definition: args.h:302
static constexpr bool is_compatible
Definition: args.h:260
constexpr args(Ts &&... arg)
Constructor from a compatible list of arguments.
Definition: args.h:276
constexpr decltype(auto) get(arg< T, Name, D >=arg< T, Name, D >{})
Get the argument matching a given name (bbm::arg type)
Definition: args.h:306
static constexpr string_literal name
name of the IDX argument
Definition: args.h:288
constexpr decltype(auto) get(arg< T, Name, D >=arg< T, Name, D >{}) const
Definition: args.h:314
static constexpr decltype(auto) _retrieve_arg(TUP &&src)
Find in a tuple of arguments the one that best matches the 'IDX'-th ARG in ARGS.
Definition: args.h:372
static constexpr bool is_cpp_compatible
Definition: args.h:263
constexpr decltype(auto) value(arg< T, Name, D >=arg< T, Name, D >{}) const
Definition: args.h:323
static constexpr bool _is_cpp_compatible_fwd(void)
Definition: args.h:252
static constexpr bool _is_cpp_compatible(void)
Check if a tuple of arguments is compatible in a classic C++ sense with ARGS.
Definition: args.h:437
static constexpr size_t _lookup(arg< T, Name, D >=arg< T, Name, D >{})
Lookup a name.
Definition: args.h:334
static constexpr size_t size
Definition: args.h:282
constexpr decltype(auto) get(void) const
Definition: args.h:298
static constexpr decltype(auto) _retrieve_args(TUP &&src, std::index_sequence< IDX... >)
Populate the 'args' from a tuple of arguments.
Definition: args.h:359
constexpr auto values(void) const
Returns a tuple of all arguments' values.
Definition: args.h:291
named container
Definition: named.h:131
Definition: string_literal.h:16
convert other types to a string literal.
A wrapper for STL containers such as tuple, pair, and array. These containers force the programmer to...