Szablon klasy - referecja dla obiektów a wartość dla typów prostych

0

Cześć,
mam szablon klasy typu:

template<class T>
class Tmp
	{
	public:
		void funkcja(T& param);
	};

Czy da się zrobić tak, aby funkcja dla typów prostych przekazywała dane przez wartość a dla typów złożonych przez referencję?
Z góry dziękuję za pomoc.

4

Pewnie, możesz sobie dispatchować po wartości, którą uzyskasz sprawdzając wymagane warunki (w przykładzie: is_trivial + rozmiar odpowiednio mały):

namespace detail {
template<typename T>
constexpr static bool use_value = std::is_trivial_v<T> &&
    (sizeof(T) <= sizeof(void*));
template<typename T, bool> struct param_type;
template<typename T> struct param_type<T, true>{ using type = T; };
template<typename T> struct param_type<T, false>{ using type = T&; };
 } // namespace detail

A następnie

template<typename T> using param_type =
    detail::param_type<T, detail::use_value<T>>::type;

Lub jeszcze prościej, z conditional_t:

namespace detail
{
template<typename T>
constexpr static bool use_value = std::is_trivial_v<T> &&
    (sizeof(T) <= sizeof(void*));
}

template<typename T> using param_type = 
    std::conditional_t<detail::use_value<T>, T, T&>;

W obu przypadkach:

template<typename T>
struct test
{
    void foo(param_type<T>) const
    {
        BARK;
    }
};

struct too_big{ int arr[10]; };

int main()
{
    test<int> t1;
    test<too_big> t2;
    int i{};
    too_big tb{};
    t1.foo(i);
    t2.foo(tb);
}

https://wandbox.org/permlink/70Zp4tHVM2F45jwk

  19 void test<T>::foo(param_type<T>) const [with T = int; param_type<T> = int]
  19 void test<T>::foo(param_type<T>) const [with T = too_big; param_type<T> = too_big&]
0

Dziękuję :)

4

Można to też zrobić bez dodatkowych komplikacji w sygnaturze metody

template<typename T, typename IsTrivial>
struct AddFunc : std::false_type{};

template<typename T>
struct AddFunc<T, std::false_type>
{
  void func(const T&) const { std::cout << "ref\n"; };
};

template<typename T>
struct AddFunc<T, std::true_type>
{
  void func(T) const { std::cout << "value\n"; };
};

template<typename T>
using AddFuncValOrRef = AddFunc<T, typename std::integral_constant<bool, std::is_trivial_v<T> && sizeof(void*)>::type>;

template<typename T>
struct Type : public AddFuncValOrRef<T>
{
};

Test

struct TestStruct
{
    int intVal{};
    double dVal{};
};

int main()
{
    const Type<int> testInt;
    const Type<TestStruct> testStruct;
    
    std::cout << "test int: ";
    testInt.func(12);
    std::cout << "test struct: ";
    testStruct.func(TestStruct{});
    
}

Rezultat https://wandbox.org/permlink/kX7LMEixSX5q7ueT

test int: value
test struct: ref

1 użytkowników online, w tym zalogowanych: 0, gości: 1