user1095108
user1095108

Reputation: 14623

clang does not compile my code, but g++ does

Can someone help me with this code:

#include <type_traits>

#include <vector>

struct nonsense { };

template <struct nonsense const* ptr, typename R>
typename std::enable_if<!std::is_void<R>::value, int>::type
fo(void* const)
{
  return 0;
}

template <struct nonsense const* ptr, typename R>
typename std::enable_if<std::is_void<R>::value, int>::type
fo(void* const)
{
  return 1;
}

typedef int (*func_type)(void*);

template <std::size_t O>
void run_me()
{
  static struct nonsense data;

  typedef std::pair<char const* const, func_type> pair_type;

  std::vector<pair_type> v;

  v.push_back(pair_type{ "a", fo<&data, int> });
  v.push_back(pair_type{ "b", fo<&data, void> });
}

int main(int, char*[])
{
  run_me<2>();

  return 0;
}

clang-3.3 does not compile this code, but g++-4.8.1 does, which of the two compiler is right? Is something wrong with the code, as I suspect?

The error reads:

a.cpp:32:15: error: no matching constructor for initialization of 'pair_type' (aka 'pair<const char *const, func_type>')
  v.push_back(pair_type{ "a", fo<&data, int> });
              ^        ~~~~~~~~~~~~~~~~~~~~~~~
a.cpp:33:15: error: no matching constructor for initialization of 'pair_type' (aka 'pair<const char *const, func_type>')
  v.push_back(pair_type{ "b", fo<&data, void> });
              ^        ~~~~~~~~~~~~~~~~~~~~~~~~

Upvotes: 4

Views: 563

Answers (1)

Marcelo Cantos
Marcelo Cantos

Reputation: 186108

Relocating static struct nonsense data outside the function gets the code to compile. I'm not savvy enough to tell you why.

To customise data for different values of the O parameter, one could define nonsense as follows…

template <size_t> struct nonsense {
    static nonsense data;
    ⋮
};

…and use it thus…

template <std::size_t O, typename R>
typename std::enable_if<!std::is_void<R>::value, int>::type
fo(void* const)
{
  // Use nonsense<O>::data
}

template <std::size_t O, typename R>
typename std::enable_if<std::is_void<R>::value, int>::type
fo(void* const)
{
  // Use nonsense<O>::data
}

⋮

template <std::size_t O>
void run_me()
{
  std::vector<std::pair<char const* const, func_type>> v;

  v.emplace_back("a", fo<O, int >);
  v.emplace_back("b", fo<O, void>);
}

Upvotes: 1

Related Questions