Как я могу использовать шаблоны для определения соответствующего метода прохождения аргумента?

StackOverflow https://stackoverflow.com/questions/1167980

  •  19-09-2019
  •  | 
  •  

Вопрос

Насколько я понимаю, при передаче объекта в функцию, которая больше, чем регистр, предпочтительнее передавать его как (const) ссылку, например:

void foo(const std::string& bar)
{
    ...
}

Это избегает необходимости выполнять потенциально дорогую копию аргумента.

Однако при передаче типа, который вписывается в регистр, передача его в качестве (const) ссылки в лучшем случае избыточно, а в худшем - медленнее:

void foo(const int& bar)
{
    ...
}

Моя проблема в том, что я хотел бы знать, как получить лучшее из обоих миров, когда я использую шаблонный класс, который должен передать любой тип:

template <typename T>
class Foo
{
  public:

    // Good for complex types, bad for small types
    void bar(const T& baz);   

    // Good for small types, but will needlessly copy complex types
    void bar2(T baz);             
};

Есть ли метод принятия решений шаблона, который позволяет мне выбрать правильный тип? Что -то, что позволило бы мне сделать,

void bar(const_nocopy<T>::type baz);

Это выберет лучший метод в зависимости от типа?


Редактировать:

После достаточного количества тестов по времени разница между двумя временами вызова различна, но очень мала. Решение, вероятно, является сомнительной микрооптимизацией для моей ситуации. Все еще, TMP это интересное ментальное упражнение.

Это было полезно?

Решение

Использовать Boost.calltraits:

#include <boost/call_traits.hpp>

template <typename T>
void most_efficient( boost::call_traits<T>::param_type t ) {
    // use 't'
}

Другие советы

Если время копирования переменной является значительным, компилятор, вероятно, в любом случае будет внедрить этот экземпляр шаблона, а эталонную вещь Const будет столь же эффективной.

Технически вы уже дали себе ответ.

Просто специализируйте no_copy<T> Шаблон для всех типов нокопии.

template <class T> struct no_copy { typedef const T& type; };

template <> struct no_copy<int> { typedef int type; };

Единственное решение, о котором я могу придумать, - это использование макроса для создания специализированной версии шаблона для небольших классов.

Первый: Использовать const & - Если реализация должна быть внедрена, аргумент Cosnt & Vs. больше не имеет большого значения.

Второй: Это лучшее, что я мог бы придумать. Не работает правильно, потому что компилятор не может вывести тип аргумента

template <typename T, bool UseRef> 
struct ArgTypeProvider {};

template <typename T>
struct ArgTypeProvider<T, true>
{
   typedef T const & ArgType;
};

template <typename T>
struct ArgTypeProvider<T, false>
{
   typedef T ArgType;
};

template <typename T>
struct ArgTypeProvider2 : public ArgTypeProvider<T, (sizeof(T)>sizeof(long)) >
{
};

// ----- example function
template <typename T>
void Foo(typename ArgTypeProvider2<T>::ArgType arg)
{
   cout << arg;
}

// ----- use
std::string s="fdsfsfsd";
// doesn't work :-(
// Foo(7);
// Foo(s);

// works :-)
Foo<int>(7);
Foo<std::string>(s);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top