Quantcast
Channel: Intel® C++ Compiler
Viewing all articles
Browse latest Browse all 1616

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

$
0
0

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;
}

 


Viewing all articles
Browse latest Browse all 1616

Trending Articles