Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion GPU/Common/GPUCommonTypeTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <type_traits>
#endif
#else
// We just reimplement some type traits in std for the GPU
// We just reimplement some type traits in std for the GPU // TODO: Check if meanwhile we can get rid of GPUCommonTypeTraits and GPUCommonArray, and just use the std headers.
namespace std
{
template <bool B, class T, class F>
Expand All @@ -35,6 +35,7 @@ struct conditional<false, T, F> {
};
template <bool B, class T, class F>
using contitional_t = typename conditional<B, T, F>::type;

template <class T, class U>
struct is_same {
static constexpr bool value = false;
Expand All @@ -45,13 +46,15 @@ struct is_same<T, T> {
};
template <class T, class U>
static constexpr bool is_same_v = is_same<T, U>::value;

template <bool B, class T = void>
struct enable_if {
};
template <class T>
struct enable_if<true, T> {
typedef T type;
};

template <class T>
struct remove_cv {
typedef T type;
Expand All @@ -68,6 +71,9 @@ template <class T>
struct remove_cv<const volatile T> {
typedef T type;
};
template <class T>
using remove_cv_t = typename remove_cv<T>::type;

template <class T>
struct remove_const {
typedef T type;
Expand All @@ -76,6 +82,9 @@ template <class T>
struct remove_const<const T> {
typedef T type;
};
template <class T>
using remove_const_t = typename remove_const<T>::type;

template <class T>
struct remove_volatile {
typedef T type;
Expand All @@ -84,6 +93,9 @@ template <class T>
struct remove_volatile<volatile T> {
typedef T type;
};
template <class T>
using remove_volatile_t = typename remove_volatile<T>::type;

template <class T>
struct is_pointer_t {
static constexpr bool value = false;
Expand All @@ -95,6 +107,36 @@ struct is_pointer_t<T*> {
template <class T>
struct is_pointer : is_pointer_t<typename std::remove_cv<T>::type> {
};

template <class T>
struct remove_reference {
typedef T type;
};
template <class T>
struct remove_reference<T&> {
typedef T type;
};
template <class T>
struct remove_reference<T&&> {
typedef T type;
};
template <class T>
using remove_reference_t = typename remove_reference<T>::type;

template <class T>
struct is_member_pointer_helper {
static constexpr bool value = false;
};
template <class T, class U>
struct is_member_pointer_helper<T U::*> {
static constexpr bool value = true;
};
template <class T>
struct is_member_pointer : is_member_pointer_helper<typename std::remove_cv<T>::type> {
};
template <class T>
static constexpr bool is_member_pointer_v = is_member_pointer<T>::value;

} // namespace std
#endif

Expand Down
2 changes: 1 addition & 1 deletion GPU/GPUTracking/Base/cuda/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ set(GPU_RTC_BIN ${CMAKE_CURRENT_BINARY_DIR}/GPUReconstructionCUDArtc)
add_custom_command(
OUTPUT ${GPU_RTC_BIN}.src
COMMAND cp ${GPUDIR}/Base/cuda/GPUReconstructionCUDAIncludesSystem.h ${GPU_RTC_BIN}.src
COMMAND ${CMAKE_CXX_COMPILER} ${GPU_RTC_DEFINES} ${GPU_RTC_INCLUDES} -std=c++${CMAKE_CUDA_STANDARD} -D__CUDA_ARCH__=${RTC_CUDA_ARCH} -D__CUDACC__ -x c++ -nostdinc -E -P ${GPU_RTC_SRC} >> ${GPU_RTC_BIN}.src
COMMAND ${CMAKE_CUDA_COMPILER} ${GPU_RTC_DEFINES} ${GPU_RTC_INCLUDES} -std=c++${CMAKE_CUDA_STANDARD} -D__CUDA_ARCH__=${RTC_CUDA_ARCH} -D__CUDACC__ -x c++ -E -Xcompiler "-nostdinc -P" ${GPU_RTC_SRC} >> ${GPU_RTC_BIN}.src
MAIN_DEPENDENCY ${GPU_RTC_SRC}
IMPLICIT_DEPENDS CXX ${GPU_RTC_SRC}
COMMAND_EXPAND_LISTS
Expand Down
4 changes: 0 additions & 4 deletions GPU/GPUTracking/Base/cuda/GPUReconstructionCUDAGenRTC.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@ int32_t GPUReconstructionCUDA::genRTC(std::string& filename, uint32_t& nCompile)
{
std::string rtcparam = std::string("#define GPUCA_RTC_CODE\n") +
std::string(GetProcessingSettings().rtc.optSpecialCode ? "#define GPUCA_RTC_SPECIAL_CODE(...) __VA_ARGS__\n" : "#define GPUCA_RTC_SPECIAL_CODE(...)\n") +
#ifndef GPUCA_HIP_WORKAROUND_CONSTEXPR // TODO: Fixme, once we have C++ P2280R4 in Clang
std::string(GetProcessingSettings().rtc.optConstexpr ? "#define GPUCA_RTC_CONSTEXPR constexpr\n" : "#define GPUCA_RTC_CONSTEXPR\n") +
#else
std::string("#define GPUCA_RTC_CONSTEXPR\n") +
#endif
GPUParamRTC::generateRTCCode(param(), GetProcessingSettings().rtc.optConstexpr);
if (filename == "") {
filename = "/tmp/o2cagpu_rtc_";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class GPUDebugTiming
bool mDo;
};

static_assert(std::is_convertible<cudaEvent_t, void*>::value, "CUDA event type incompatible to deviceEvent");
static_assert(std::is_convertible_v<cudaEvent_t, void*>, "CUDA event type incompatible to deviceEvent");

} // namespace o2::gpu

Expand Down
7 changes: 1 addition & 6 deletions GPU/GPUTracking/Base/hip/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ set(GPU_RTC_BIN ${CMAKE_CURRENT_BINARY_DIR}/GPUReconstructionHIPrtc)
add_custom_command(
OUTPUT ${GPU_RTC_BIN}.src
COMMAND cp ${GPUDIR}/Base/hip/GPUReconstructionHIPIncludesSystem.h ${GPU_RTC_BIN}.src
COMMAND ${CMAKE_CXX_COMPILER} ${GPU_RTC_DEFINES} ${GPU_RTC_INCLUDES} -std=c++${CMAKE_HIP_STANDARD} -D__HIPCC__ -D__HIP_DEVICE_COMPILE__ -x c++ -nostdinc -E -P ${GPU_RTC_SRC} >> ${GPU_RTC_BIN}.src
COMMAND ${CMAKE_HIP_COMPILER} ${GPU_RTC_DEFINES} ${GPU_RTC_INCLUDES} -std=c++${CMAKE_HIP_STANDARD} -D__HIPCC__ -D__HIP_DEVICE_COMPILE__ -x c++ -nostdinc -E -P ${GPU_RTC_SRC} >> ${GPU_RTC_BIN}.src
MAIN_DEPENDENCY ${GPU_RTC_SRC}
IMPLICIT_DEPENDS CXX ${GPU_RTC_SRC}
DEPENDS ${MODULE}_HIPIFIED
Expand Down Expand Up @@ -270,8 +270,3 @@ add_dependencies(GPUTrackingHIPExternalProvider O2::GPUTracking) # must not depe
if(NOT DEFINED GPUCA_HIP_HIPIFY_FROM_CUDA OR "${GPUCA_HIP_HIPIFY_FROM_CUDA}")
add_dependencies(GPUTrackingHIPExternalProvider ${MODULE}_HIPIFIED)
endif()

set_source_files_properties("${GPUCA_HIP_SOURCE_DIR}/GPUReconstructionHIPGenRTC.cxx"
TARGET_DIRECTORY O2::GPUTrackingHIP
PROPERTIES
COMPILE_DEFINITIONS "GPUCA_HIP_WORKAROUND_CONSTEXPR")
2 changes: 1 addition & 1 deletion GPU/GPUTracking/Base/opencl/GPUReconstructionOCL.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

#include <map>

static_assert(std::is_convertible<cl_event, void*>::value, "OpenCL event type incompatible to deviceEvent");
static_assert(std::is_convertible_v<cl_event, void*>, "OpenCL event type incompatible to deviceEvent");

#define GPUErrorReturn(...) \
{ \
Expand Down
67 changes: 67 additions & 0 deletions GPU/GPUTracking/Definitions/GPUGetConstexpr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// \file GPUGetConstexpr.h
/// \author David Rohr

#ifndef GPUGETCONSTEXPR_H
#define GPUGETCONSTEXPR_H

#include "GPUCommonDef.h"
#include "GPUCommonTypeTraits.h"

// This is a temporary workaround required for clang (with c++20), until we can go to C++23 with P2280R4, which allows getting constexpr static values from references

#if defined(__clang__) && __cplusplus >= 202002L && __cplusplus < 202302L

namespace o2::gpu::internal
{

#define GPUCA_GET_CONSTEXPR(obj, val) ( \
std::is_member_pointer_v<decltype(&std::remove_reference_t<decltype(obj)>::val)> ? o2::gpu::internal::getConstexpr(&std::remove_reference_t<decltype(obj)>::val, o2::gpu::internal::getConstexprHelper<decltype(&std::remove_reference_t<decltype(obj)>::val), decltype(&obj)>(&obj).value) : o2::gpu::internal::getConstexpr(&std::remove_reference_t<decltype(obj)>::val, o2::gpu::internal::getConstexprHelper<decltype(&std::remove_reference_t<decltype(obj)>::val), decltype(&obj)>().value))

template <class T, class S>
struct getConstexprHelper;

template <class T, class S>
requires(!std::is_member_pointer_v<T>)
struct getConstexprHelper<T, S> {
GPUdi() constexpr getConstexprHelper(const void* = nullptr) {}
static constexpr const void* value = nullptr;
};

template <class T, class S>
requires(std::is_member_pointer_v<T>)
struct getConstexprHelper<T, S> {
GPUdi() constexpr getConstexprHelper(const S& v) : value(v) {}
GPUdDefault() constexpr getConstexprHelper() = default;
const S value = nullptr;
};

GPUdi() constexpr auto getConstexpr(const auto* v, const void* = nullptr)
{
return *v;
}

GPUdi() constexpr auto getConstexpr(const auto v, const auto w)
{
return w->*v;
}

} // namespace o2::gpu::internal

#else // __clang__

#define GPUCA_GET_CONSTEXPR(obj, val) (obj).val

#endif

#endif // GPUGETCONSTEXPR_H
4 changes: 2 additions & 2 deletions GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ int64_t GPUTPCGMMerger::GetTrackLabelA(const S& trk) const
{
GPUTPCGMSectorTrack* sectorTrack = nullptr;
int32_t nClusters = 0;
if constexpr (std::is_same<S, GPUTPCGMBorderTrack&>::value) {
if constexpr (std::is_same_v<S, GPUTPCGMBorderTrack&>) {
sectorTrack = &mSectorTrackInfos[trk.TrackID()];
nClusters = sectorTrack->OrigTrack()->NHits();
} else {
Expand All @@ -244,7 +244,7 @@ int64_t GPUTPCGMMerger::GetTrackLabelA(const S& trk) const
auto acc = GPUTPCTrkLbl<false, GPUTPCTrkLbl_ret>(resolveMCLabels<T>(GetConstantMem()->ioPtrs.clustersNative ? GetConstantMem()->ioPtrs.clustersNative->clustersMCTruth : nullptr, GetConstantMem()->ioPtrs.mcLabelsTPC), 0.5f);
for (int32_t i = 0; i < nClusters; i++) {
int32_t id;
if constexpr (std::is_same<S, GPUTPCGMBorderTrack&>::value) {
if constexpr (std::is_same_v<S, GPUTPCGMBorderTrack&>) {
const GPUTPCTracker& tracker = GetConstantMem()->tpcTrackers[sectorTrack->Sector()];
const GPUTPCHitId& ic = tracker.TrackHits()[sectorTrack->OrigTrack()->FirstHitID() + i];
id = tracker.Data().ClusterDataIndex(tracker.Data().Row(ic.RowIndex()), ic.HitIndex()) + GetConstantMem()->ioPtrs.clustersNative->clusterOffset[sectorTrack->Sector()][0];
Expand Down
5 changes: 3 additions & 2 deletions GPU/GPUTracking/Merger/GPUTPCGMO2Output.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "DataFormatsTPC/PIDResponse.h"
#include "TPCFastTransform.h"
#include "CorrectionMapsHelper.h"
#include "GPUGetConstexpr.h"

#ifndef GPUCA_GPUCODE
#include "SimulationDataFormat/ConstMCTruthContainer.h"
Expand Down Expand Up @@ -141,10 +142,10 @@ GPUdii() void GPUTPCGMO2Output::Thread<GPUTPCGMO2Output::output>(int32_t nBlocks

oTrack.setChi2(tracks[i].GetParam().GetChi2());
auto& outerPar = tracks[i].OuterParam();
if GPUCA_RTC_CONSTEXPR (param.par.dodEdx) {
if GPUCA_RTC_CONSTEXPR (GPUCA_GET_CONSTEXPR(param.par, dodEdx)) {
if (param.dodEdxEnabled) {
oTrack.setdEdx(tracksdEdx[i]);
if GPUCA_RTC_CONSTEXPR (param.rec.tpc.dEdxClusterRejectionFlagMask != param.rec.tpc.dEdxClusterRejectionFlagMaskAlt) {
if GPUCA_RTC_CONSTEXPR (GPUCA_GET_CONSTEXPR(param.rec.tpc, dEdxClusterRejectionFlagMask) != GPUCA_GET_CONSTEXPR(param.rec.tpc, dEdxClusterRejectionFlagMaskAlt)) {
oTrack.setdEdxAlt(tracksdEdxAlt[i]);
} else {
oTrack.setdEdxAlt(tracksdEdx[i]);
Expand Down
11 changes: 6 additions & 5 deletions GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "GPUTPCConvertImpl.h"
#include "GPUTPCGMMergerTypes.h"
#include "GPUParam.inc"
#include "GPUGetConstexpr.h"

#ifdef GPUCA_CADEBUG_ENABLED
#include "../utils/qconfig.h"
Expand Down Expand Up @@ -216,12 +217,12 @@ GPUd() bool GPUTPCGMTrackParam::Fit(GPUTPCGMMerger* GPUrestrict() merger, int32_
continue;
}
} else if (allowModification && lastRow != 255 && CAMath::Abs(cluster.row - lastRow) > 1) {
if GPUCA_RTC_CONSTEXPR (param.par.dodEdx) {
if GPUCA_RTC_CONSTEXPR (GPUCA_GET_CONSTEXPR(param.par, dodEdx)) {
bool dodEdx = param.dodEdxEnabled && param.rec.tpc.adddEdxSubThresholdClusters && iWay == nWays - 1 && CAMath::Abs(cluster.row - lastRow) == 2 && cluster.leg == clusters[maxN - 1].leg;
dodEdx = AttachClustersPropagate(merger, cluster.sector, lastRow, cluster.row, iTrk, cluster.leg == clusters[maxN - 1].leg, prop, inFlyDirection, GPUCA_MAX_SIN_PHI, dodEdx);
if (dodEdx) {
dEdx.fillSubThreshold(lastRow - wayDirection);
if GPUCA_RTC_CONSTEXPR (param.rec.tpc.dEdxClusterRejectionFlagMask != param.rec.tpc.dEdxClusterRejectionFlagMaskAlt) {
if GPUCA_RTC_CONSTEXPR (GPUCA_GET_CONSTEXPR(param.rec.tpc, dEdxClusterRejectionFlagMask) != GPUCA_GET_CONSTEXPR(param.rec.tpc, dEdxClusterRejectionFlagMaskAlt)) {
dEdxAlt.fillSubThreshold(lastRow - wayDirection);
}
}
Expand Down Expand Up @@ -371,7 +372,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(GPUTPCGMMerger* GPUrestrict() merger, int32_
CADEBUG(printf("Reinit linearization\n"));
prop.SetTrack(this, prop.GetAlpha());
}
if GPUCA_RTC_CONSTEXPR (param.par.dodEdx) {
if GPUCA_RTC_CONSTEXPR (GPUCA_GET_CONSTEXPR(param.par, dodEdx)) {
if (param.dodEdxEnabled && iWay == nWays - 1 && cluster.leg == clusters[maxN - 1].leg) { // TODO: Costimize flag to remove, and option to remove double-clusters
bool acc = (clusterState & param.rec.tpc.dEdxClusterRejectionFlagMask) == 0, accAlt = (clusterState & param.rec.tpc.dEdxClusterRejectionFlagMaskAlt) == 0;
if (acc || accAlt) {
Expand All @@ -395,7 +396,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(GPUTPCGMMerger* GPUrestrict() merger, int32_
if (acc) {
dEdx.fillCluster(qtot, qmax, cluster.row, cluster.sector, mP[2], mP[3], merger->GetConstantMem()->calibObjects, zz, pad, relTime);
}
if GPUCA_RTC_CONSTEXPR (param.rec.tpc.dEdxClusterRejectionFlagMask != param.rec.tpc.dEdxClusterRejectionFlagMaskAlt) {
if GPUCA_RTC_CONSTEXPR (GPUCA_GET_CONSTEXPR(param.rec.tpc, dEdxClusterRejectionFlagMask) != GPUCA_GET_CONSTEXPR(param.rec.tpc, dEdxClusterRejectionFlagMaskAlt)) {
if (accAlt) {
dEdxAlt.fillCluster(qtot, qmax, cluster.row, cluster.sector, mP[2], mP[3], merger->GetConstantMem()->calibObjects, zz, pad, relTime);
}
Expand Down Expand Up @@ -436,7 +437,7 @@ GPUd() bool GPUTPCGMTrackParam::Fit(GPUTPCGMMerger* GPUrestrict() merger, int32_

if (param.par.dodEdx && param.dodEdxEnabled) {
dEdx.computedEdx(merger->MergedTracksdEdx()[iTrk], param);
if GPUCA_RTC_CONSTEXPR (param.rec.tpc.dEdxClusterRejectionFlagMask != param.rec.tpc.dEdxClusterRejectionFlagMaskAlt) {
if GPUCA_RTC_CONSTEXPR (GPUCA_GET_CONSTEXPR(param.rec.tpc, dEdxClusterRejectionFlagMask) != GPUCA_GET_CONSTEXPR(param.rec.tpc, dEdxClusterRejectionFlagMaskAlt)) {
dEdxAlt.computedEdx(merger->MergedTracksdEdxAlt()[iTrk], param);
}
}
Expand Down
8 changes: 4 additions & 4 deletions GPU/GPUTracking/qa/GPUQAHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class GPUTPCTrkLbl
}
inline void addLabel(uint32_t elementId)
{
if constexpr (std::is_same<T, AliHLTTPCClusterMCWeight>::value) {
if constexpr (std::is_same_v<T, AliHLTTPCClusterMCWeight>) {
for (uint32_t i = 0; i < sizeof(mClusterLabels[elementId]) / sizeof(mClusterLabels[elementId].fClusterID[0]); i++) {
const auto& element = mClusterLabels[elementId].fClusterID[i];
if (element.fMCID >= 0) {
Expand Down Expand Up @@ -101,7 +101,7 @@ class GPUTPCTrkLbl
}
}
auto& bestLabel = mLabels[bestLabelNum].first;
if constexpr (std::is_same<T, AliHLTTPCClusterMCWeight>::value && WEIGHT) {
if constexpr (std::is_same_v<T, AliHLTTPCClusterMCWeight> && WEIGHT) {
*labelWeight = bestLabel.fWeight;
*totalWeight = mTotalWeight;
*maxCount = bestLabelCount;
Expand Down Expand Up @@ -147,7 +147,7 @@ struct GPUTPCTrkLbl_ret {
template <bool WEIGHT = false, class U = void, class T, template <class> class S, typename... Args>
static inline auto GPUTPCTrkLbl(const S<T>* x, Args... args)
{
if constexpr (std::is_same<U, void>::value) {
if constexpr (std::is_same_v<U, void>) {
return internal::GPUTPCTrkLbl<WEIGHT, T, S<T>>(x, args...);
} else {
return internal::GPUTPCTrkLbl<WEIGHT, T, S<T>, U>(x, args...);
Expand All @@ -159,7 +159,7 @@ static inline auto GPUTPCTrkLbl(const AliHLTTPCClusterMCLabel* x, Args... args)
{
using S = AliHLTTPCClusterMCLabel;
using T = AliHLTTPCClusterMCWeight;
if constexpr (std::is_same<U, void>::value) {
if constexpr (std::is_same_v<U, void>) {
return internal::GPUTPCTrkLbl<WEIGHT, T, S>(x, args...);
} else {
return internal::GPUTPCTrkLbl<WEIGHT, T, S, U>(x, args...);
Expand Down
2 changes: 1 addition & 1 deletion GPU/GPUTracking/utils/bitfield.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class bitfield
}

#if !defined(GPUCA_GPUCODE_DEVICE)
static_assert(std::is_integral<S>::value, "Storage type non integral");
static_assert(std::is_integral_v<S>, "Storage type non integral");
static_assert(sizeof(S) >= sizeof(T), "Storage type has insufficient capacity");
#endif

Expand Down
8 changes: 4 additions & 4 deletions GPU/GPUTracking/utils/qconfig.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ static inline int32_t qAddOptionMainTupleElem(qConfigSettings<typename qSettings
qConfigSettings<T> settings = settingsTup;
return (qAddOptionType<T>(settings, ref, i, argv, argc, def));
}
template <typename T, int32_t index = 0, int32_t left = std::tuple_size<T>::value>
template <typename T, int32_t index = 0, int32_t left = std::tuple_size_v<T>>
struct qAddOptionMainTupleStruct {
static inline int32_t qAddOptionMainTuple(qConfigSettings<typename qSettingsType<T>::settingsType> settings, T& tup, int32_t& i, const char** argv, const int argc)
{
Expand Down Expand Up @@ -157,13 +157,13 @@ struct qConfigType {
// Recursive handling of additional settings
static inline void qProcessSetting(qConfigSettings<T>& settings, qmin_t<T> minval)
{
static_assert(!std::is_same<T, bool>::value, "min option not supported for boolean settings");
static_assert(!std::is_same_v<T, bool>, "min option not supported for boolean settings");
settings.checkMin = true;
settings.min = minval.v;
}
static inline void qProcessSetting(qConfigSettings<T>& settings, qmax_t<T> maxval)
{
static_assert(!std::is_same<T, bool>::value, "max option not supported for boolean settings");
static_assert(!std::is_same_v<T, bool>, "max option not supported for boolean settings");
settings.checkMax = true;
settings.max = maxval.v;
}
Expand Down Expand Up @@ -244,7 +244,7 @@ struct qConfigType {
static inline void qConfigHelpOption(const char* name, const char* type, const char* def, const char* optname, char optnameshort, const char* preopt, char preoptshort, int32_t optionType, const char* help, Args&&... args)
{
auto settings = qConfigGetSettings(args...);
const bool boolType = optionType != 1 && std::is_same<T, bool>::value;
const bool boolType = optionType != 1 && std::is_same_v<T, bool>;
const char* arguments = settings.doSet ? " (" : (settings.doDefault || optionType == 1 || boolType) ? " [arg] (" : optionType == 2 ? " [...] (" : " arg (";
char argBuffer[4] = {0};
uint32_t argBufferPos = 0;
Expand Down