I'm experiencing some strange occurrences regarding varidaic templates that I never saw before.
In order to keep it simple i'll give a simple example of what I was trying to achieve, the real code is a bit more involved.
So I have one function that looks like:
template <typename T, typename F, typename ... Args>
static T Func( std::string str, Args&& ... args )
{
... Do something
}
I then call this function a number of times from different locations, where most times the passed types are different. But when I debug this, when I look for the symbol of Func, I get that the same function address has a number of different symbols:
00000000`70ba4ae0 Func<unsigned long,unsigned long (__stdcall*)(wchar_t const *),wchar_t const *>
00000000`70ba4ae0 Func<void *,void * (__stdcall*)(unsigned int),unsigned int>
00000000`70ba4ae0 Func<int,int (__stdcall*)(void *),void *>
So they are all basically the same function. When I try to call for example:
call Func<void *,void * (__stdcall*)(unsigned int),unsigned int>
In the debugger I see:
call Func<int,int (__stdcall*)(void *),void *>
I can see that there is a generated symbol for every template function instance, but every such instance that has the same number of arguments and the arguments are the same byte-size are just linked to one function.
While I can understand why this may happen, but is there a way to force each function to be standalone?
The issue was indeed COMDAT folding. Turning off the OPT:ICF and OPT:REF flags did the trick. Although worth noting that compiling with VS 2017 with the flags produced more "sensible" results than compiling the same code with VS 2013.
Related
I've been reading the chapter 5 of "C++ Templates, The complete guide", and i've seen the concept of "template template" templates, so tried myself.
In a template class, i've declared my template like this:
template <typename TipoClave, typename TipoDato,
template <class Elem, class Alloc = allocator<Elem>> class Lista = vector>
And this works. My problem comes when I try to use a different container than the default.
My class is as follows:
class Tabla
{
public:
struct Celda {
TipoClave clave;
TipoDato dato;
};
Tabla(unsigned tam)
{
t.resize(tam);
}
///< Some other functions
private:
typedef Lista<Celda> ListaDatos;
Lista<ListaDatos> t;
};
And then, when I try to use it from the main program like this:
int main (void)
{
Tabla<string,Alumno,array> tabla(200);
///< Some stuff
return 0;
}
But this line Tabla<string,Alumno,array> tabla(200); does not compile, getting me an error like:
test_tabla_t.cpp: In function ‘int main()’: test_tabla_t.cpp:20:27:
error: type/value mismatch at argument 3 in template parameter list
for ‘template class Lista> class Tabla’ Tabla
tabla(200);
I've tried to use Tabla<string,Alumno,vector> tabla(200);, and it works, so I don't know how to solve this error.
Assuming you're trying to use std::array, it does not take an Allocator template parameter. Its second argument is the size of the array.
template<
class T,
std::size_t N
> struct array;
You haven't mentioned how experienced you are with C++, but since you're trying to learn more, I'll say that I've been using C++ for nearly a decade and can count on one hand the number of times I've used template template parameters.
In this case, you want Lista to be "something that acts like a sequence container[1]", you might like to read about concepts[2], which may make it into C++20. They allow you to tell the compiler the interface you want a template parameter to have.
In the meantime, it might be easier to declare Lista as a plain template parameter.
[1] http://en.cppreference.com/w/cpp/concept/SequenceContainer
[2] https://en.wikipedia.org/wiki/Concepts_(C%2B%2B)
Supposing one needs to obtain a logical value based on a
pack of template parameters, is there a reason to prefer an alias approach
vs a function approach?
Example:
template<bool...> struct bool_pack;
template<bool... bs>
using all_true = std::is_same<bool_pack<bs..., true>,
bool_pack<true, bs...>>;
as opposed to
template<class none=void>
constexpr bool all_true() { return true; }
template<bool First, bool... Rest>
constexpr bool all_true() {
return First and all_true<Rest...>();
}
Time required for compiling your example implementations
... should be measured, of course. That said, I have seen micro-benchmarks where the std::is_same approach leads to significantly shorter compile times; even compared to the C++17 fold expression (true && ... && bs) with the respective compilers. The recursive "function approach" you gave as an example should be clearly inferior in compile-time performance.
Note, however, that one could surely offer the most convenient interface by providing a wrapper around the most "efficient" (regarding compile-time effort) implementation.
Convenience in using the "interface"
Given these two choices, I would prefer the alias approach. If you need the result of that helper as a type (for inheritance, template-metaprogramming with specializations, or for tag dispatch), the alias yields cleaner syntax compared to, say, std::bool_constant<all_true_v<some_condition(), some_other_condition()>()>. In the other direction, it is simple to obtain a value of type bool from the alias: all_true<some_condition(), some_other_condition()>{} (relying on implicit type conversion).
Since C++14, yet another (fancy?) choice is to provide a value by a constexpr variable template which has either type std::true_type or std::false_type. By implicit conversion to bool it can readily be used where plain true or false is required, but it can also be passed as a function argument without losing its compile-time guarantee.
template<bool... bs>
constexpr auto all_true_c = typename std::is_same<
bool_pack<true, bs...>, bool_pack<bs..., true>
>::type{};
It may be a good strategy to follow the naming conventions used in the <type_traits> header of modern C++ providing both forms. If some utility is supposed to provide a value, one finds helper variable templates such as std::is_same_v:
template<class T, class U>
inline constexpr bool is_same_v = is_same<T, U>::value;// (since C++17)
if some helper is supposed to provide a type, one finds helper types such as std::decay_t:
template<class T>
using decay_t = typename decay<T>::type;// (since C++14)
... in addition to the conventional utilities without suffix, respectively.
Context:
I'm trying to learn smart pointers and I came across a case I don't understand.
I'm creating an unordered_map of unique_ptr<list<int>>. Declared as following:
unique_ptr<unordered_map<uint32_t, unique_ptr<list<uint32_t>>>> mymap;
The map and its contents are private data of a class and I want them to be destroyed when the class is destroyed. Therefore I use a unique_ptr for the map and for each list.
Problem:
When I call emplace, like so:
mymap->emplace(index, make_unique<list<uint32_t>>());
My program compiles just fine. It also works when I call insert creating pair explicitly:
mymap->insert(std::make_pair(index, std::make_unique<std::list<uint32_t>>()));
However, the following line:
mymap->insert({index, make_unique<std::list<uint32_t>>()});
produces the following errors (GCC in Linux Ubuntu)):
/usr/include/c++/5/ext/new_allocator.h:120:4: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const unsigned int; _T2 = std::unique_ptr >]’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
From the this answer I learned that the difference between the two methods is that insert copies or moves a key-value pair into the container, while emplace builds it in place. So perhaps the problem is that I'm not properly using the unique_ptr?
Question: Why the first two calls succeed while the third fails?
Referring to my previous question, as the explanation is required in detail.
How is the following code snippet working, fundamental and C++ 03 equivalent ?
auto get_option_name = [](const std::pair<const std::string, std::string>& p) -> const std::string& {
return p.first;
};
It's equivalent to:
class Extractor {
// Definition of "function call" operator, to use instance
// of this class like a function
const std::string& operator()(const std::pair<const std::string, std::string>& p) {
return p.first;
}
};
Extractor get_option_name;
More information on wikipedia or on stackoverflow
#Garf365's answer is the best. A lambda and a class like that one really are the most similar - you can use them just like callable functions, and pass around pointers and references to them.
However, you may also want to learn about using function templates to do this work during compile-time, especially when passing them as a parameter to another template, as in using the boost library.
I was curious if there was an improvement in the complexity of the code the compiler produced by using a function template, and there was!
Look for yourself:
Using a "function object" or "functor" class (or whatever they are called) - is 187 lines of assembly from GCC, and 237 lines of assembly from clang.
Using a function template - only 65 lines of assembly from GCC, and 84 from clang. That's a reduction by a factor of 300%!
Thank you for asking the question and leading me to look into it!
I have a type A that's designed to be implicitly casted to type B. Here's an example case I'd like to use it in:
// Current implementation:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
[](const A& a) -> B { return a; }); // Thanks, Kerrek SB.
// Ideal implementation - Won't compile, expected '(' after 'static_cast'.
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
static_cast<B>);
What can I do to make the latter option compile?
static_cast<B>, while it is invoked with function-call syntax cannot be passed like other callable things. E.g., there's no way to use & to get a function pointer to it.
You can use a short little lambda to achieve something similar to passing a function pointer to static_cast<B>, as you do in your current implementation:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b),
[](const A& a) -> B { return a; });
Another option--in this particular case--would be to construct a vector<B> from the vector<A>:
std::vector<B> vec_of_b(vec_of_a.begin(), vec_of_a.end());
(This answer is a summary of the comments on both the question and bipll's answer.)
Build a functor enclosing static_cast:
template <typename T>
struct StaticCast
{
template <typename U>
T operator()(const U& rhs)
{
return static_cast<T>(rhs);
}
};
With this, you can call std::transform:
std::transform(vec_of_a.begin(), vec_of_a.end(), std::back_inserter(vec_of_b), StaticCast<b>());
It can be used in the case the output vector is already defined in place of the lambda shown in comments. If not, prefer the constructor mentioned in another answer**.
This functor version is compliant with C++98 if needed -- even if OP is tagged C++11, it may be worthy to note this point.
** Note that with this particular constructor, a warning C4244 is raised with VS compiler (tested with VS2017).
Yes, that's the way anonymous functions work in C++, and static_cast is not a function so you cannot pass its address as the mapped function. You'll have to deal with it.
You cannot use a constructor either.