icc 14.0.2 C++11 bug: Cannot find templated function although it exists?

icc 14.0.2 C++11 bug: Cannot find templated function although it exists?

The following example code doesn't compile with icc 14.0.2 in C++11 mode, although it seems to be standard compliant code (and both g++ 4.8.1 and clang++ compile it without complaint).

This may or may not be related to https://software.intel.com/en-us/forums/topic/500790 / DPD200252873, but I couldn't really figure out what causes the problems. It might be a name-lookup issue with helper templates being lookup up in the wrong namespaces, or the variadic templates in general. I couldn't really narrow it down any further...

The first version in main.cpp that directly calls the internal function from the THDetail-namespace seems to work, the public one in TH:: which does exactly the same thing is not found or otherwise causes unhappiness.

/*
> icc -v
icc version 14.0.2 (gcc version 4.8.0 compatibility)
> icc --std=c++11 yet_another_icc_bug.cpp
yet_another_icc_bug.cpp(53): error: no instance of function template "TH::GetEveryNthElement" matches the argument list
            argument types are: (std::tuple<int, double, float>)
  	auto t0 = TH::GetEveryNthElement<1u, 0u>(t2); // no work
  	          ^

compilation aborted for yet_another_icc_bug.cpp (code 2)


Same code compiles fine with g++ or clang++.
May (or not) be related to https://software.intel.com/en-us/forums/topic/500790 / DPD200252873.

*/

#include <tuple>
#include <type_traits>
#include <utility>

namespace TH {

template<unsigned ...Is> struct Indices { };

template<unsigned N, unsigned ...Is> struct BuildIndices : BuildIndices<N-1, N-1, Is...> { };

template<unsigned ...Is> struct BuildIndices<0, Is...> : Indices<Is...> { };

template<typename T>
using Value = typename std::remove_cv<typename std::remove_reference<T>::type>::type;

template<typename Tuple>
using IndicesForTuple = BuildIndices<std::tuple_size<Value<Tuple> >::value>;

namespace THDetail
{

template<unsigned N, unsigned Offset, typename Tuple, unsigned ...Is>
inline auto GetEveryNthElementImpl(Tuple &&t, Indices<Is ...>)
-> decltype(std::tuple<typename std::tuple_element<Offset + N * Is, Value<Tuple> >::type ...>(
  std::get<Offset + N * Is>(std::forward<Tuple>(t)) ...))
{
  static_assert(N >= 1u, "Index-multiplier smaller than 1!");
  return std::tuple<typename std::tuple_element<Offset + N * Is, Value<Tuple> >::type ...>(
    std::get<Offset + N * Is>(std::forward<Tuple>(t)) ...);
}

} // end namespace THDetail

template<unsigned N, unsigned Offset = 0u, typename Tuple>
inline auto GetEveryNthElement(Tuple &&t)
-> decltype(THDetail::GetEveryNthElementImpl<N, Offset>(std::forward<Tuple>(t),
  BuildIndices<(std::tuple_size<Value<Tuple> >::value - Offset + N - 1u) / N>()))
{
  static_assert(Offset < N, "Offset is larger than index-multiplier!");
  return THDetail::GetEveryNthElementImpl<N, Offset>(std::forward<Tuple>(t),
    BuildIndices<(std::tuple_size<Value<Tuple> >::value - Offset + (N - 1u)) / N>());
}

template<unsigned N, unsigned Offset, typename Tuple>
using TupleEveryNthElement = decltype(GetEveryNthElement<N, Offset, Tuple>(std::declval<Tuple>()));

} // end namespace TH

int main(int argc, char const *argv[])
{
	std::tuple<int, double, float> t2;
	auto tm1 = TH::THDetail::GetEveryNthElementImpl<1u, 0u>(t2, TH::BuildIndices<(std::tuple_size<decltype(t2)>::value - 0u + (1u - 1u)) / 1>()); // works
	auto t0 = TH::GetEveryNthElement<1u, 0u>(t2); // no work
	return 0;
}

 

AttachmentSize
Download yet_another_icc_bug.cpp2.55 KB
7 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

icc 15.0.0 Beta Update 2 is also affected.

 

This is not related to cq #252873 which was a bug having to do with variadic template argument deduction and has been fixed since March 2014.

A small example of the problem you are seeing is below. As you can see, the problem seems to be the explicit template arguments used in the late specified return type.

I have submitted this bug as DPD200358811 in our internal bugs database. Thank you for reporting it.

template<typename N, typename Tuple>
#ifdef OK
int fooImpl(N,Tuple);
#else
int fooImpl(Tuple);
#endif

template<typename Tuple>
auto foo(Tuple t)
#ifdef OK
-> decltype(fooImpl(3,t));
#else
-> decltype(fooImpl<int>(t));
#endif

int main()
{
  foo(4);
  return 0;
}

Thanks Judith.

I'm not sure if this is relevant here, but as they template arguments in my case are not types but PODs (unsigned in this case) I unfortunately cannot let the compiler deduce them and need to specify them explicitly.

I'd made my own bug report (as I did register a premium account for the XE 2015 beta) as 6000058730 if that helps.

As mentioned in the bug report, I have a set of unit tests for the file the above code was reduced from, which could help fix more bugs faster if you're interested. They fail to compile in many, many places with icc.

 

 

Hmmmm. If in line 53 and 57 in my example I explicitly specify Tuple as last template argument to the implementation function (instead of letting the compiler re-deduce it), it seems to compile....

 

Yes Daniel your original example uses a non-type template argument instead of a template argument but I think it's the same underlying problem. I realize this bug may not be easy to workaround in your case, sorry about that.

If you have other test cases that you think are showing different compiler bugs please file them as separate bugs (either through Premier or here).  That would be much appreciated! We can always close them as duplicates if we figure out they are the same. I know sometimes it's really hard to tell.

thanks,

Judy

I've updated my bug report 6000058730 with a self-contained unit-test for our TemplateHelper.hpp header that triggers many more of these C++11 template issues.

Leave a Comment

Please sign in to add a comment. Not a member? Join today